Remove all plugins / install base theme

This commit is contained in:
Tony Volpe
2024-06-18 16:14:48 -04:00
parent ecc33d62f0
commit 95cb30b884
7455 changed files with 0 additions and 1722920 deletions

View File

@@ -1,59 +0,0 @@
<?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 );
}
}

View File

@@ -1,334 +0,0 @@
<?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' ) );
} elseif ( in_array( RG_CURRENT_PAGE, array( 'admin-ajax.php' ) ) ) {
add_action( 'wp_ajax_gf_get_changelog', array( $this, 'ajax_display_changelog' ) );
}
}
// 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' ) );
}
/**
* Displays messages for the Gravity Forms listing on the Plugins page.
*
* Displays if Gravity Forms isn't supported.
*
* @since Unknown
* @since 2.4.15 Update to improve multisite updates.
*/
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 );
}
}
//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 ) {
if ( empty( $option ) ) {
return $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();
}
$plugin = array(
'plugin' => $this->_path,
'url' => $this->_url,
'slug' => $this->_slug,
'package' => $version_info['url'] ? str_replace( '{KEY}', $key, $version_info['url'] ) : '',
'new_version' => $version_info['version'],
'id' => '0',
);
//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 ] );
$option->no_update[ $this->_path ] = (object) $plugin;
} else {
$option->response[ $this->_path ] = (object) $plugin;
}
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;
}
/**
* Get changelog with admin-ajax.php in GFForms::maybe_display_update_notification().
*
* @since 2.4.15
*/
public function ajax_display_changelog() {
check_admin_referer();
$this->display_changelog();
}
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' ),
);
$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='" . esc_attr( GFCommon::get_support_url() ). "'>", '</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( GFCommon::get_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&amp;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 ) . '&section=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&amp;plugin=' . urlencode( $plugin_file ), 'upgrade-plugin_' . $plugin_file );
$details_url = self_admin_url( 'plugin-install.php?tab=plugin-information&plugin=' . urlencode( $this->_slug ) . '&section=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>', "&nbsp;<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
}
}

View File

@@ -1,310 +0,0 @@
<?php
if ( ! class_exists( 'GFForms' ) ) {
die();
}
if ( ! class_exists( 'GF_Background_Process' ) ) {
require_once GF_PLUGIN_DIR_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 ) {
$addon = $item['addon'];
$feed = $item['feed'];
$feed_name = rgars( $feed, 'meta/feed_name' ) ? $feed['meta']['feed_name'] : rgars( $feed, 'meta/feedName' );
$callable = array( is_string( $addon ) ? $addon : get_class( $addon ), 'get_instance' );
if ( is_callable( $callable ) ) {
$addon = call_user_func( $callable );
}
if ( ! $addon instanceof GFFeedAddOn ) {
GFCommon::log_error( __METHOD__ . "(): attempted feed (#{$feed['id']} - {$feed_name}) for entry #{$item['entry_id']} for {$feed['addon_slug']} but add-on could not be found. Bailing." );
return false;
}
$entry = GFAPI::get_entry( $item['entry_id'] );
$addon_slug = $addon->get_slug();
// 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_slug} but entry could not be found. Bailing." );
return false;
}
$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_slug}. Bailing." );
return false;
}
$item = $this->increment_attempts( $item );
$max_attempts = 1;
$form = $this->filter_form( GFAPI::get_form( $item['form_id'] ), $entry );
/**
* Allow the number of retries to be modified before the feed is abandoned.
*
* if $max_attempts > 1 and if GFFeedAddOn::process_feed() throws an error or returns a WP_Error then the feed
* will be attempted again. Once the maximum number of attempts has been reached then the feed will be abandoned.
*
* @since 2.4
*
* @param int $max_attempts The maximum number of retries allowed. Default: 1.
* @param array $form The form array
* @param array $entry The entry array
* @param string $addon_slug The add-on slug
* @param array $feed The feed array
*/
$max_attempts = apply_filters( 'gform_max_async_feed_attempts', $max_attempts, $form, $entry, $addon_slug, $feed );
// Remove task if it was attempted too many times but failed to complete.
if ( $item['attempts'] > $max_attempts ) {
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 the item for another attempt
return $item;
}
if ( is_wp_error( $returned_entry ) ) {
/** @var WP_Error $returned_entry */
// Log the error.
call_user_func( array(
$addon,
'log_error',
), __METHOD__ . "(): Unable to process feed due to error: {$returned_entry->get_error_message()}" );
// Return the item for another attempt
return $item;
}
// 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
* @since 2.6.5 Removed the $context param.
* @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 ) {
// 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( $string, 0, $number, $file, $line );
} 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 GF_Feed_Processor
*/
function gf_feed_processor() {
return GF_Feed_Processor::get_instance();
}

View File

@@ -1,927 +0,0 @@
<?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' => wp_strip_all_tags( __( '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 = isset( $menu_items['results']['sub_menu_items'] ) ? $menu_items['results']['sub_menu_items'] : $menu_items['results']['single_menu_item'];
$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' => admin_url( "admin.php?page=gf_entries&view=gf_results_{$this->_slug}&id={$form_id}" ),
'menu_class' => 'gf_form_toolbar_results',
'link_class' => $link_class,
'capabilities' => $this->_capabilities,
'single_menu_item' => $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;
}
?>
<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>
<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 GFForms::admin_header(array(), true ) ;?>
<?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="gform-settings-panel__content postbox">
<h2><?php echo $this->_search_title ?></h2>
<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__( 'Include results if', 'gravityforms' ),
'tooltip' => 'gresults_filters',
'markup' => '<div class="gform-settings-field__conditional-logic"><div id="gresults-results-field-filters-container">
<!-- placeholder populated by js -->
</div></div>',
),
'start_date' => array(
'label' => esc_attr__( 'Start date', 'gravityforms' ),
'markup' => '<div class="gform-settings-field gform-settings-field__date_time">
<span class="gform-settings-input__container"><input type="text" id="gresults-results-filter-date-start" name="start" value="' . esc_attr( $start_date ) . '"/><button type="button" class="ui-datepicker-trigger"><span class="screen-reader-text">'.esc_html__( 'Open Date Picker', 'gravityforms' ).'</span><svg width="18" height="18" role="presentation" focusable="false" fill="#9092B2" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M13.0909 1.6364V1.231C13.0909.5513 13.6357 0 14.3182 0c.6778 0 1.2273.5468 1.2273 1.2311v.4053h.8254c.8997 0 1.6291.7349 1.6291 1.6288v13.106C18 17.2707 17.2721 18 16.3709 18H1.6291C.7294 18 0 17.2651 0 16.3712V3.2652c0-.8996.728-1.6288 1.6291-1.6288h.8254V1.231C2.4545.5513 2.9993 0 3.6818 0c.6778 0 1.2273.5468 1.2273 1.2311v.4053h2.4545V1.231C7.3636.5513 7.9084 0 8.591 0c.6778 0 1.2273.5468 1.2273 1.2311v.4053h3.2727zM1.6364 7.3636v9h14.7272v-9H1.6364z"></path></svg></button></span>
</div>',
),
'end_date' => array(
'label' => esc_attr__( 'End date', 'gravityforms' ),
'markup' => '<div class="gform-settings-field gform-settings-field__date_time" >
<span class="gform-settings-input__container"><input type="text" id="gresults-results-filter-date-end" name="end" value="' . esc_attr( $end_date ) . '"/><button type="button" class="ui-datepicker-trigger"><span class="screen-reader-text">'.esc_html__( 'Open Date Picker', 'gravityforms' ).'</span><svg width="18" height="18" role="presentation" focusable="false" fill="#9092B2" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M13.0909 1.6364V1.231C13.0909.5513 13.6357 0 14.3182 0c.6778 0 1.2273.5468 1.2273 1.2311v.4053h.8254c.8997 0 1.6291.7349 1.6291 1.6288v13.106C18 17.2707 17.2721 18 16.3709 18H1.6291C.7294 18 0 17.2651 0 16.3712V3.2652c0-.8996.728-1.6288 1.6291-1.6288h.8254V1.231C2.4545.5513 2.9993 0 3.6818 0c.6778 0 1.2273.5468 1.2273 1.2311v.4053h2.4545V1.231C7.3636.5513 7.9084 0 8.591 0c.6778 0 1.2273.5468 1.2273 1.2311v.4053h3.2727zM1.6364 7.3636v9h14.7272v-9H1.6364z"></path></svg></button></span>
</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="gform-settings-field__header"><label class='gform-settings-label'><?php echo $filter['label'] ?><?php gform_tooltip( rgar( $filter, 'tooltip' ), 'tooltip_bottomleft' ) ?></label></div>
<?php
echo $filter['markup'];
}
?>
<div id="gresults-results-filter-buttons">
<input type="submit" id="gresults-results-filter-submit-button"
class="button primary large"
value="<?php esc_attr_e( 'Apply filters', 'gravityforms' ); ?>">
<input type="button" id="gresults-results-filter-clear-button"
class="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='gform-spinner'></i>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
<div class="gresults-filter-loading" style="display:none;margin:0 5px 10px 0;">
<i class='gform-spinner'></i>&nbsp;
<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">&nbsp;
</div>
</div>
<?php
else :
_e( 'This form does not have any fields that can be used for results', 'gravityforms' );
endif ?>
</div>
<?php GFForms::admin_footer() ?>
<?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 gform-settings-panel' id='gresults-results-field-{$field_id}'>";
$html .= "<header class='gform-settings-panel__header'><legend class='gform-settings-panel__title'>" . esc_html( GFCommon::get_label( $field ) ) . '</legend></header>';
$html .= '<div class="gform-settings-panel__content">' . 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 + 20 ) );
$chart_options = array(
'isStacked' => true,
'height' => ( $chart_area_height + $bar_height ),
'fontSize' => 14,
'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' ) . '&nbsp;' . 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' ) . '&nbsp;' . 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>" . wp_kses_post( $content ) . "</li>";
$c ++;
}
}
$offset += $page_size;
} while ( $c < $page_size && ! empty( $leads ) );
if ( ! empty( $leads ) ) {
$more_remaining = true;
}
return $field_results;
}
}
}

View File

@@ -1,60 +0,0 @@
.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;
}

View File

@@ -1 +0,0 @@
.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 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: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}

View File

@@ -1,292 +0,0 @@
/* --------- 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;
}
.gform-admin .gresults-filter-loading .gform-spinner {
display: inline-block;
}
.gf-results .gf-result-box {
background: #fff;
border-radius: 3px;
border: 1px solid #e3e6ef;
box-shadow: 0 1px 4px rgb(18 25 97 / 8%);
padding: 1.562rem 1rem;
}
.gf-results .gf-result-box {
margin-right: 0;
margin-bottom: 1.25rem;
}
.gf-results .gf-result-box__primary {
display: flex;
}
@media screen and ( min-width: 782px ) {
.gf-results {
display: flex;
justify-content: space-between;
margin-bottom: 1.25rem;
}
.gf-results .gf-result-box {
flex: 1 1 0px;
margin-right: 1.25rem;
margin-bottom: 0;
}
.gf-results .gf-result-box:last-child {
margin-right: 0;
}
}
.gresults-results-field {
margin-bottom:20px;
}
.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-content {
padding:12px;
border-top: 1px solid #EBEBF2
}
.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-results-filter-content #gform-no-filters {
color: #242748;
}
.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; }

View File

@@ -1 +0,0 @@
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{table-layout:fixed}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}.gform-admin .gresults-filter-loading .gform-spinner{display:inline-block}.gf-results .gf-result-box{background:#fff;border-radius:3px;border:1px solid #e3e6ef;box-shadow:0 1px 4px rgb(18 25 97 / 8%);padding:1.562rem 1rem}.gf-results .gf-result-box{margin-right:0;margin-bottom:1.25rem}.gf-results .gf-result-box__primary{display:flex}@media screen and (min-width:782px){.gf-results{display:flex;justify-content:space-between;margin-bottom:1.25rem}.gf-results .gf-result-box{flex:1 1 0px;margin-right:1.25rem;margin-bottom:0}.gf-results .gf-result-box:last-child{margin-right:0}}.gresults-results-field{margin-bottom:20px}.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 outside none}ul.gresults-results-field-content{margin:10px}td.gresults-rank-field-rank,td.gresults-rank-field-score{width:110px}.gsurvey-rank-field-results table{width:100%}#gresults-results-filter-content{padding:12px;border-top:1px solid #ebebf2}.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-results-filter-content #gform-no-filters{color:#242748}.gresults-add,.gresults-remove{margin-top:2px;vertical-align:middle;cursor:pointer}.gresults-add{margin-left:5px}#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-field ul li label{margin-left:5px}.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}

View File

@@ -1,308 +0,0 @@
/* ------------------ Field Map ------------------ */
.gforms_form_settings.form-table .settings-field-map-table thead th {
font-weight: bold;
text-align: left;
padding-left:0px;
}
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 td:last-child {
white-space: nowrap;
}
.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: 210px;
}
.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-key-container.supports-merge-tags input:not(:only-child),
.settings-field-map-table .custom-value-container.supports-merge-tags input:not(:only-child) {
padding-right: 50px;
}
.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 .tooltip-merge-tag {
background-position: center;
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;
z-index: 99;
}
.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;
}
.add-item, .remove-item {
color: #444;
}
.mt-gaddon-editor {
float: right;
position: relative;
right: 0.625rem;
top: 2.8125rem;
z-index: 1;
}
div#tab_notification .mt-gaddon-editor {
top: 3.3125rem;
}
html[dir="rtl"] .mt-gaddon-editor {
float: left;
}
.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;
font-size: 1.25rem;
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;
}
}

File diff suppressed because one or more lines are too long

View File

@@ -1,2 +0,0 @@
<?php
//Nothing to see here

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -1,2 +0,0 @@
<?php
//Nothing to see here

View File

@@ -1,111 +0,0 @@
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="gform-icon gform-icon--drag-indicator 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();
}

View File

@@ -1 +0,0 @@
var GFFeedOrder=function(e){var o=this,i=jQuery;o.init=function(){o.options=e;i(".wp-list-table thead tr, .wp-list-table tfoot tr").append('<th class="sort-column"></th>'),i(".wp-list-table tbody tr").append('<td class="sort-column"><i class="gform-icon gform-icon--drag-indicator feed-sort-handle"></i></td>'),o.initSorting()},o.initSorting=function(){i(".wp-list-table tbody").sortable({cursor:"move",handle:".feed-sort-handle",placeholder:"feed-placeholder",tolerance:"pointer",create:function(){i(".wp-list-table").addClass("feed-list-sortable")},helper:o.fixSortableColumnWidths,start:o.setPlaceholderHeight,update:o.updateFeedOrder})},o.fixSortableColumnWidths=function(e,t){var o=t.children(),t=t.clone();return t.children().each(function(e){i(this).width(o.eq(e).width())}),t},o.getFeedOrder=function(){return i('.wp-list-table tbody .check-column input[type="checkbox"]').map(function(){return i(this).val()}).get()},o.setPlaceholderHeight=function(e,t){i(".wp-list-table .feed-placeholder").height(t.item.height())},o.updateFeedOrder=function(e,t){i.ajax(ajaxurl,{method:"POST",dataType:"JSON",data:{action:"gf_save_feed_order",addon:o.options.addon,form_id:o.options.formId,feed_order:o.getFeedOrder(),nonce:o.options.nonce}})},this.init()};

View File

@@ -1,136 +0,0 @@
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() {
var data = jQuery( '#' + self.options.fieldId ).val();
self.data = data ? jQuery.parseJSON( data ) : null;
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: '<i class="gficon-add"></i>',
removeButtonMarkup: '<i class="gficon-subtract"></i>',
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();
};

View File

@@ -1 +0,0 @@
var gfieldmap=function(e){var a=this;return a.options=e,a.UI=jQuery("#gaddon-setting-row-"+a.options.fieldName),a.init=function(){a.bindEvents(),a.setupData(),a.setupRepeater()},a.bindEvents=function(){a.UI.on("change",'select[name="_gaddon_setting_'+a.options.keyFieldName+'"]',function(){var e=jQuery(this),t=e.data("chosen")?e.siblings(".chosen-container"):e.data("select2")?e.siblings(".select2-container"):e,n=e.siblings(".custom-key-container");"gf_custom"==e.val()&&t.fadeOut(function(){n.fadeIn().focus()})}),a.UI.on("click","a.custom-key-reset",function(e){e.preventDefault();var t=jQuery(this).parents(".custom-key-container"),n=t.siblings("select.key"),i=n.data("chosen")?n.siblings(".chosen-container"):n.data("select2")?n.siblings(".select2-container"):n;t.fadeOut(function(){t.find("input").val("").change(),n.val("").trigger("change"),i.fadeIn().focus()})}),a.UI.closest("form").on("submit",function(e){jQuery('[name^="_gaddon_setting_'+a.options.fieldName+'_"]').each(function(e){jQuery(this).removeAttr("name")})})},a.setupData=function(){var e=jQuery("#"+a.options.fieldId).val();a.data=e?jQuery.parseJSON(e):null,a.data||(a.data=[{key:"",value:"",custom_key:""}])},a.setupRepeater=function(){var e=0<a.options.limit?a.options.limit:0;a.UI.find("tbody.repeater").repeater({limit:e,items:a.data,addButtonMarkup:'<i class="gficon-add"></i>',removeButtonMarkup:'<i class="gficon-subtract"></i>',callbacks:{add:function(e,t,n){var i=t.find('select[name="_gaddon_setting_'+a.options.keyFieldName+'"]');(!n.custom_key&&0<i.length?t.find(".custom-key-container"):t.find(".key")).hide(),gform.doAction("gform_fieldmap_add_row",e,t,n)},save:function(e,t){t=jQuery.extend({},t);for(var n=0;n<t.length;n++)""!=t[n].custom_key&&(t[n].custom=1,t[n].key=t[n].custom_key),delete t[n].custom_key;jQuery("#"+a.options.fieldId).val(jQuery.toJSON(t))}}})},a.init()};

View File

@@ -1,234 +0,0 @@
var GFFrontendFeeds = function( args ) {
var self = this,
$ = jQuery;
/**
* Initialize Feed Ordering
*/
self.init = function() {
// Assign options to instance.
self.options = args;
self.triggerInputIds = self.getTriggerInputIds( self.options.feeds );
self.activeFeeds = [];
self.evaluateFeeds();
self.bindEvents();
};
self.bindEvents = function() {
gform.addAction( 'gform_input_change', function( elem, formId, inputId ) {
var fieldId = parseInt( inputId ) + '';
var isTriggeredInput = $.inArray( inputId, self.triggerInputIds ) !== -1 || $.inArray( fieldId , self.triggerInputIds ) !== -1 ;
if( self.options.formId == formId && isTriggeredInput ) {
self.evaluateFeeds();
}
} );
};
self.evaluateFeeds = function() {
var feed, isMatch, isActivated;
for( i = 0; i < self.options.feeds.length; i++ ) {
feed = self.options.feeds[ i ];
isMatch = self.evaluateFeed( feed, self.options.formId );
isActivated = self.isFeedActivated( feed );
if( ! isMatch && isActivated !== null ) {
self.deactivateFeed( feed );
} else if( isMatch && ! isActivated && ( ! feed.isSingleFeed || ( feed.isSingleFeed && self.hasPriority( feed.feedId, feed.addonSlug ) ) ) ) {
self.activateFeed( feed );
}
}
/**
* Fires after the conditional logic on the form has been evaluated.
*
* @since 2.4
*
* @param array $feeds A collection of feed objects.
* @param int $formId The form id.
*/
gform.doAction( 'gform_frontend_feeds_evaluated', self.options.feeds, self.options.formId, self );
gform.doAction( 'gform_frontend_feeds_evaluated_{0}'.gformFormat( self.options.formId ), self.options.feeds, self.options.formId, self );
gform.doAction( 'gform_{0}_frontend_feeds_evaluated'.gformFormat( feed.addonSlug ), self.options.feeds, self.options.formId, self );
gform.doAction( 'gform_{0}_frontend_feeds_evaluated_{0}'.gformFormat( feed.addonSlug, self.options.formId ), self.options.feeds, self.options.formId, self );
};
self.evaluateFeed = function( feed, formId ) {
// Feeds with no configured conditional logic always a match.
if( ! feed.conditionalLogic ) {
return true;
}
return gf_get_field_action( formId, feed.conditionalLogic ) == 'show';
};
self.getTriggerInputIds = function() {
var inputIds = [];
for( var i = 0; i < self.options.feeds.length; i++ ) {
var feed = self.options.feeds[ i ];
if( ! feed.conditionalLogic ) {
continue;
}
for( var j = 0; j < feed.conditionalLogic.rules.length; j++ ) {
var rule = self.options.feeds[i].conditionalLogic.rules[j];
if( $.inArray( rule.fieldId, inputIds ) == -1 ) {
inputIds.push( rule.fieldId );
}
}
}
return inputIds;
};
self.isFeedActivated = function( feed ) {
if( typeof feed != 'object' ) {
feed = self.getFeed( feed );
if( ! feed ) {
return false;
}
}
return typeof feed.isActivated != 'undefined' ? feed.isActivated : null;
};
self.getFeed = function( feedId ) {
for( var i = 0; i < self.options.feeds.length; i++ ) {
var feed = self.options.feeds[ i ];
if( feed.feedId == feedId ) {
return feed;
}
}
return false;
};
self.getFeedsByAddon = function( addonSlug, currentFeed, onlyActive ) {
var feeds = [];
for( var i = 0; i < self.options.feeds.length; i++ ) {
var feed = self.options.feeds[ i ];
if( feed.addonSlug == addonSlug
&& ! ( currentFeed && feed.feedId == currentFeed.feedId )
) {
if( onlyActive ) {
if( self.isFeedActivated( feed ) ) {
feeds.push( feed );
}
} else {
feeds.push( feed );
}
}
}
return feeds;
};
self.activateFeed = function( feeds ) {
if( feeds.feedId ) {
feeds = [ feeds ];
}
for( var i = 0; i < feeds.length; i++ ) {
var feed = feeds[ i ];
feed.isActivated = true;
/**
* Fires after the conditional logic on the form has been evaluated and the feed has been found to be active.
*
* @since 2.4
*
* @param array $feeds A collection of feed objects.
* @param int $formId The form id.
*/
gform.doAction( 'gform_frontend_feed_activated', feed, self.options.formId );
gform.doAction( 'gform_frontend_feed_activated_{0}'.gformFormat( self.options.formId ), feed, self.options.formId );
gform.doAction( 'gform_{0}_frontend_feed_activated'.gformFormat( feed.addonSlug ), feed, self.options.formId );
gform.doAction( 'gform_{0}_frontend_feed_activated_{0}'.gformFormat( feed.addonSlug, self.options.formId ), feed, self.options.formId );
if( feed.isSingleFeed ) {
self.deactivateFeed( self.getFeedsByAddon( feed.addonSlug, feed ) );
}
}
};
self.deactivateFeed = function( feeds ) {
if( feeds.feedId ) {
feeds = [ feeds ];
}
for( var i = 0; i < feeds.length; i++ ) {
var feed = feeds[ i ],
isActivated = self.isFeedActivated( feed );
if( isActivated === null || isActivated === false ) {
continue;
}
feed.isActivated = false;
/**
* Fires after the conditional logic on the form has been evaluated and the feed has become inactive.
*
* @since 2.4
*
* @param array $feeds A collection of feed objects.
* @param int $formId The form id.
*/
gform.doAction( 'gform_frontend_feed_deactivated', feed, self.options.formId );
gform.doAction( 'gform_frontend_feed_deactivated_{0}'.gformFormat( self.options.formId ), feed, self.options.formId );
gform.doAction( 'gform_{0}_frontend_feed_deactivated'.gformFormat( feed.addonSlug ), feed, self.options.formId );
gform.doAction( 'gform_{0}_frontend_feed_deactivated_{0}'.gformFormat( feed.addonSlug, self.options.formId ), feed, self.options.formId );
}
};
self.hasPriority = function( feedId, addonSlug ) {
var addonFeeds = self.getFeedsByAddon( addonSlug );
for( var i = 0; i <= addonFeeds.length; i++ ) {
var feed = addonFeeds[i];
if( feed.feedId != feedId && feed.isActivated ) {
return false;
} else if ( feed.feedId == feedId ) {
return true;
}
}
return false;
};
this.init();
};

View File

@@ -1 +0,0 @@
var GFFrontendFeeds=function(o){var r=this,f=jQuery;r.init=function(){r.options=o,r.triggerInputIds=r.getTriggerInputIds(r.options.feeds),r.activeFeeds=[],r.evaluateFeeds(),r.bindEvents()},r.bindEvents=function(){gform.addAction("gform_input_change",function(o,e,t){var d=parseInt(t)+"",t=-1!==f.inArray(t,r.triggerInputIds)||-1!==f.inArray(d,r.triggerInputIds);r.options.formId==e&&t&&r.evaluateFeeds()})},r.evaluateFeeds=function(){var o,e,t;for(i=0;i<r.options.feeds.length;i++)o=r.options.feeds[i],e=r.evaluateFeed(o,r.options.formId),t=r.isFeedActivated(o),e||null===t?e&&!t&&(!o.isSingleFeed||o.isSingleFeed&&r.hasPriority(o.feedId,o.addonSlug))&&r.activateFeed(o):r.deactivateFeed(o);gform.doAction("gform_frontend_feeds_evaluated",r.options.feeds,r.options.formId,r),gform.doAction("gform_frontend_feeds_evaluated_{0}".gformFormat(r.options.formId),r.options.feeds,r.options.formId,r),gform.doAction("gform_{0}_frontend_feeds_evaluated".gformFormat(o.addonSlug),r.options.feeds,r.options.formId,r),gform.doAction("gform_{0}_frontend_feeds_evaluated_{0}".gformFormat(o.addonSlug,r.options.formId),r.options.feeds,r.options.formId,r)},r.evaluateFeed=function(o,e){return!o.conditionalLogic||"show"==gf_get_field_action(e,o.conditionalLogic)},r.getTriggerInputIds=function(){for(var o=[],e=0;e<r.options.feeds.length;e++){var t=r.options.feeds[e];if(t.conditionalLogic)for(var d=0;d<t.conditionalLogic.rules.length;d++){var n=r.options.feeds[e].conditionalLogic.rules[d];-1==f.inArray(n.fieldId,o)&&o.push(n.fieldId)}}return o},r.isFeedActivated=function(o){return!("object"!=typeof o&&!(o=r.getFeed(o)))&&(void 0!==o.isActivated?o.isActivated:null)},r.getFeed=function(o){for(var e=0;e<r.options.feeds.length;e++){var t=r.options.feeds[e];if(t.feedId==o)return t}return!1},r.getFeedsByAddon=function(o,e,t){for(var d=[],n=0;n<r.options.feeds.length;n++){var i=r.options.feeds[n];i.addonSlug!=o||e&&i.feedId==e.feedId||t&&!r.isFeedActivated(i)||d.push(i)}return d},r.activateFeed=function(o){o.feedId&&(o=[o]);for(var e=0;e<o.length;e++){var t=o[e];t.isActivated=!0,gform.doAction("gform_frontend_feed_activated",t,r.options.formId),gform.doAction("gform_frontend_feed_activated_{0}".gformFormat(r.options.formId),t,r.options.formId),gform.doAction("gform_{0}_frontend_feed_activated".gformFormat(t.addonSlug),t,r.options.formId),gform.doAction("gform_{0}_frontend_feed_activated_{0}".gformFormat(t.addonSlug,r.options.formId),t,r.options.formId),t.isSingleFeed&&r.deactivateFeed(r.getFeedsByAddon(t.addonSlug,t))}},r.deactivateFeed=function(o){o.feedId&&(o=[o]);for(var e=0;e<o.length;e++){var t=o[e],d=r.isFeedActivated(t);null!==d&&!1!==d&&(t.isActivated=!1,gform.doAction("gform_frontend_feed_deactivated",t,r.options.formId),gform.doAction("gform_frontend_feed_deactivated_{0}".gformFormat(r.options.formId),t,r.options.formId),gform.doAction("gform_{0}_frontend_feed_deactivated".gformFormat(t.addonSlug),t,r.options.formId),gform.doAction("gform_{0}_frontend_feed_deactivated_{0}".gformFormat(t.addonSlug,r.options.formId),t,r.options.formId))}},r.hasPriority=function(o,e){for(var t=r.getFeedsByAddon(e),d=0;d<=t.length;d++){var n=t[d];if(n.feedId!=o&&n.isActivated)return!1;if(n.feedId==o)return!0}return!1},this.init()};

View File

@@ -1,166 +0,0 @@
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() {
var data = jQuery( '#' + self.options.fieldId ).val();
self.data = data ? jQuery.parseJSON( data ) : null;
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: '<i class="gficon-add"></i>',
removeButtonMarkup: '<i class="gficon-subtract"></i>',
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 && key_select.val() !== 'gf_custom' ) ) {
$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 && value_select.val() !== 'gf_custom' ) ) {
$elem.find( '.custom-value-container' ).hide();
} else {
$elem.find( '.value' ).hide();
}
if ( self.options.mergeTags ) {
new gfMergeTagsObj( form, $elem.find( '.custom-value-container input' ) );
$elem.find( '.custom-value-container' ).addClass( 'supports-merge-tags' );
}
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();
};

View File

@@ -1 +0,0 @@
var GFGenericMap=function(e){var i=this;return i.options=e,i.UI=jQuery("#gaddon-setting-row-"+i.options.fieldName),i.init=function(){i.bindEvents(),i.setupData(),i.setupRepeater()},i.bindEvents=function(){i.UI.on("change",'select[name="_gaddon_setting_'+i.options.keyFieldName+'"]',function(){var e=jQuery(this),n=e.data("chosen")?e.siblings(".chosen-container"):e.data("select2")?e.siblings(".select2-container"):e,t=e.siblings(".custom-key-container");"gf_custom"==e.val()&&n.fadeOut(function(){t.fadeIn().focus()})}),i.UI.on("change",'select[name="_gaddon_setting_'+i.options.valueFieldName+'"]',function(){var e=jQuery(this),n=e.data("chosen")?e.siblings(".chosen-container"):e.data("select2")?e.siblings(".select2-container"):e,t=e.siblings(".custom-value-container");"gf_custom"==e.val()&&n.fadeOut(function(){t.fadeIn().focus()})}),i.UI.on("click","a.custom-key-reset",function(e){e.preventDefault();var n=jQuery(this).parents(".custom-key-container"),t=n.siblings("select.key"),a=t.data("chosen")?t.siblings(".chosen-container"):t.data("select2")?t.siblings(".select2-container"):t;n.fadeOut(function(){n.find("input").val("").change(),t.val("").trigger("change"),a.fadeIn().focus()})}),i.UI.on("click","a.custom-value-reset",function(e){e.preventDefault();var n=jQuery(this).parents(".custom-value-container"),t=n.siblings("select.value"),a=t.data("chosen")?t.siblings(".chosen-container"):t.data("select2")?t.siblings(".select2-container"):t;n.fadeOut(function(){n.find("input").val("").change(),t.val("").trigger("change"),a.fadeIn().focus()})}),i.UI.closest("form").on("submit",function(e){jQuery('[name^="_gaddon_setting_'+i.options.fieldName+'_"]').each(function(e){jQuery(this).removeAttr("name")})})},i.setupData=function(){var e=jQuery("#"+i.options.fieldId).val();i.data=e?jQuery.parseJSON(e):null,i.data||(i.data=[{key:"",value:"",custom_key:"",custom_value:""}])},i.setupRepeater=function(){var e=0<i.options.limit?i.options.limit:0;i.UI.find("tbody.repeater").repeater({limit:e,items:i.data,addButtonMarkup:'<i class="gficon-add"></i>',removeButtonMarkup:'<i class="gficon-subtract"></i>',callbacks:{add:function(e,n,t){var a=n.find('select[name="_gaddon_setting_'+i.options.keyFieldName+'"]'),a=((!t.custom_key&&0<a.length&&"gf_custom"!==a.val()?n.find(".custom-key-container"):n.find(".key")).hide(),n.find('select[name="_gaddon_setting_'+i.options.valueFieldName+'"]'));(!t.custom_value&&0<a.length&&"gf_custom"!==a.val()?n.find(".custom-value-container"):n.find(".value")).hide(),i.options.mergeTags&&(new gfMergeTagsObj(form,n.find(".custom-value-container input")),n.find(".custom-value-container").addClass("supports-merge-tags")),window.hasOwnProperty("gform")&&gform.doAction("gform_fieldmap_add_row",e,n,t)},save:function(e,n){jQuery("#"+i.options.fieldId).val(JSON.stringify(n))}}})},i.init()};

View File

@@ -1,46 +0,0 @@
function loadBillingLength(setting_name){
var intervals = window[setting_name + "_intervals"]
if(!intervals)
return;
var unit = jQuery("#" + setting_name + "_unit").val();
var min = gform.utils.escapeHtml( intervals[unit]["min"] );
var max = gform.utils.escapeHtml( 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.success === true ) {
jQuery( "#gform_payment_status" ).html( gform.utils.escapeHtml( gaddon_payment_strings.subscriptionCanceled ) );
jQuery( "#cancelsub" ).hide();
} else {
jQuery( "#cancelsub" ).prop( "disabled", false );
if ( response.success === false ) {
alert( gaddon_payment_strings.subscriptionError );
}
}
}
);
}

View File

@@ -1 +0,0 @@
function loadBillingLength(n){var e=window[n+"_intervals"];if(e){for(var s=jQuery("#"+n+"_unit").val(),i=gform.utils.escapeHtml(e[s].min),c=gform.utils.escapeHtml(e[s].max),e=jQuery("#"+n+"_length"),t=e.val(),r="",a=i;a<=c;a++)r+="<option value='"+a+"' "+(t==a?"selected='selected'":"")+">"+a+"</option>";e.html(r)}}function cancel_subscription(n){confirm(gaddon_payment_strings.subscriptionCancelWarning)&&(jQuery("#subscription_cancel_spinner").show(),jQuery("#cancelsub").prop("disabled",!0),jQuery.post(ajaxurl,{action:"gaddon_cancel_subscription",entry_id:n,gaddon_cancel_subscription:gaddon_payment_strings.subscriptionCancelNonce},function(n){jQuery("#subscription_cancel_spinner").hide(),!0===n.success?(jQuery("#gform_payment_status").html(gform.utils.escapeHtml(gaddon_payment_strings.subscriptionCanceled)),jQuery("#cancelsub").hide()):(jQuery("#cancelsub").prop("disabled",!1),!1===n.success&&alert(gaddon_payment_strings.subscriptionError))}))}

View File

@@ -1,251 +0,0 @@
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 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('');
gform.utils.trigger( { event: 'gform/page_loader/show' } );
filterButtons.attr('disabled', 'disabled');
}
})
.done(function (response) {
if (!response || response === -1) {
gform.utils.trigger( { event: 'gform/page_loader/hide' } );
results.html(gresultsStrings.ajaxError);
} else {
if (response.status === "complete") {
filterButtons.removeAttr('disabled');
gform.utils.trigger( { event: 'gform/page_loader/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 {
gform.utils.trigger( { event: 'gform/page_loader/hide' } );
results.html(gresultsStrings.ajaxError);
}
}
})
.fail(function (error) {
filterButtons.removeAttr('disabled');
results.fadeTo("fast", 1);
var msg = error.statusText;
gform.utils.trigger( { event: 'gform/page_loader/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").off('click', '.gform-add').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( window ).on( 'load', 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('.ui-datepicker-trigger').on('click', function() {
jQuery(this).parent().find('input').datepicker( 'show' );
});
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();
}
});

File diff suppressed because one or more lines are too long

View File

@@ -1,131 +0,0 @@
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 );

View File

@@ -1 +0,0 @@
window.GFToken=null,function(n){GFToken=function(i){for(var t in i)i.hasOwnProperty(t)&&(this[t]=i[t]);this.form=n("#gform_"+this.formId),this.init=function(){var s=this;this.tokens={},this.isAjax||gformInitSpinner(this.formId),this.hasPages&&n(document).bind("gform_page_loaded",function(i,t,e){t==s.formId&&e!=s.pageCount&&s.saveEntryData()}),this.form.submit(function(){s.onSubmit()})},this.onSubmit=function(){this.form.data("gftokensubmitting")||(event.preventDefault(),this.form.data("gftokensubmitting",!0),this.saveEntryData(),this.processTokens())},this.processTokens=function(){for(var i in this.feeds){this.active_feed=this.feeds[i];var t,e={billing_fields:{},id:this.active_feed.id,name:this.active_feed.name};for(t in this.active_feed.billing_fields)field_id=this.active_feed.billing_fields[t],e.billing_fields[t]=this.entry_data[field_id];window[this.callback].createToken(e,this)}},this.saveEntryData=function(){var t=this,e="input_"+this.formId+"_";this.entry_data||(this.entry_data={}),this.form.find('input[id^="'+e+'"], select[id^="'+e+'"], textarea[id^="'+e+'"]').each(function(){var i=n(this).attr("id").replace(e,"").replace("_",".");0<=n.inArray(i,t.fields)&&(t.entry_data[i]=n(this).val())})},this.saveToken=function(i){this.tokens[this.active_feed.id]={feed_id:this.active_feed.id,response:i},this.tokens.length==this.feeds.length&&(this.form.find(this.responseField).val(n.toJSON(this.tokens)),this.form.submit())},this.init()}}(jQuery);

View File

@@ -1,2 +0,0 @@
<?php
//Nothing to see here

View File

@@ -1,329 +0,0 @@
/**
* 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' ), escapeAttr( 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();
};

View File

@@ -1 +0,0 @@
jQuery.fn.repeater=function(e){var i=this;return i.options=jQuery.extend(!0,{},{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}}},e),i.elem=jQuery(this),i.items=i.options.items,i.callbacks=i.options.callbacks,i._template=i.options.template,i._baseObj=i.items[0],i.init=function(){return i.stashTemplate(),i.elem.addClass("repeater"),i.refresh(),i.bindEvents(),i},i.bindEvents=function(){i.options.saveEvents=i.getNamespacedEvents(i.options.saveEvents),i.elem.off("click.repeater","a.add-item"),i.elem.on("click.repeater","a.add-item:not(.inactive)",function(){i.addNewItem(this)}),i.elem.off("click.repeater","a.remove-item"),i.elem.on("click.repeater","a.remove-item",function(e){i.removeItem(this)}),i.elem.off(i.options.saveEvents,i.options.saveElements),i.elem.on(i.options.saveEvents,i.options.saveElements,function(){i.save()})},i.stashTemplate=function(){i._template||(i._template=i.elem.html()),i._template=jQuery.trim(i._template)},i.addItem=function(e,t){var n=i.getItemMarkup(e,t),n=jQuery(n).addClass("item-"+t);i.callbacks.beforeAdd(i,n,e,t),i.append(n),i.populateSelects(e,t),i.callbacks.add(i,n,e,t)},i.getItemMarkup=function(e,t){var n,a=i._template;for(n in e)e.hasOwnProperty(n)&&(a=(a=(a=a.replace(/{i}/g,t)).replace("{buttons}",i.getRepeaterButtonsMarkup(t))).replace(new RegExp("{"+n+"}","g"),escapeAttr(e[n])));return a},i.getRepeaterButtonsMarkup=function(e){return i.callbacks.repeaterButtons(i,e)||i.getDefaultButtonsMarkup(e)},i.getDefaultButtonsMarkup=function(e){var t='<a class="add-item '+(i.items.length>=i.options.limit&&0!==i.options.limit?"inactive":"")+'" data-index="'+e+'">'+i.options.addButtonMarkup+"</a>";return i.items.length>i.options.minItemCount&&(t+='<a class="remove-item" data-index="'+e+'">'+i.options.removeButtonMarkup+"</a>"),'<div class="repeater-buttons">'+t+"</div>"},i.populateSelects=function(e,t){for(var n in e){var a;e.hasOwnProperty(n)&&(a=i.elem.find("."+n+"_"+t)).is("select")&&(jQuery.isArray(e[n])?a.val(e[n]):a.find('option[value="'+e[n]+'"]').prop("selected",!0))}},i.addNewItem=function(e,t){var n=i.isElement(e),t=parseInt(void 0!==t?t:n?parseInt(jQuery(e).attr("data-index"),10)+1:i.items.length,10),n=n?i.getBaseObject():e;return i.callbacks.beforeAddNew(i,t),i.items.splice(t,0,n),i.callbacks.addNew(i,t),i.refresh().save(),i},i.removeItem=function(e){e=i.isElement(e)?jQuery(e).attr("data-index"):e;i.callbacks.beforeRemove(i,e),delete i.items[e],i.callbacks.remove(i,e),i.save().refresh()},i.refresh=function(){i.elem.empty();for(var e=0;e<i.items.length;e++)i.addItem(i.items[e],e);return i},i.save=function(){for(var e=i.getBaseObjectKeys(),t=[],n=0;n<i.items.length;n++)if(void 0!==i.items[n]){for(var a={},r=0;r<e.length;r++){var s=e[r],o=i.elem.find("."+s+"_"+n).val();a[s]=void 0!==o&&o}t.push(a)}return i.items=t,i.callbacks.save(i,t),i},i.getBaseObjectKeys=function(){for(var e=[],t=0<i.items.length?i.items:[i._baseObj],n=0;n<t.length;n++)if(void 0!==t[n]){for(var a in t[n])t[n].hasOwnProperty(a)&&e.push(a);break}return e},i.getBaseObject=function(){for(var e={},t=i.getBaseObjectKeys(),n=0;n<t.length;n++)e[t[n]]="";return e},i.getNamespacedEvents=function(e){for(var e=e.split(" "),t=[],n=0;n<e.length;n++)t.push(e[n]+".repeater");return t.join(" ")},i.isElement=function(t){try{return t instanceof HTMLElement}catch(e){return"object"==typeof t&&1===t.nodeType&&"object"==typeof t.style&&"object"==typeof t.ownerDocument}},i.init()};

File diff suppressed because it is too large Load Diff

View File

@@ -1,67 +0,0 @@
<?php
namespace Gravity_Forms\Gravity_Forms\Assets\Admin_Dependencies;
use Gravity_Forms\Gravity_Forms\Assets\GF_Dependencies;
use Gravity_Forms\Gravity_Forms\GF_Service_Container;
use Gravity_Forms\Gravity_Forms\GF_Service_Provider;
/**
* Class GF_Admin_Script_Dependencies
*
* @since 2.6
*
* @package Gravity_Forms\Gravity_Forms\Assets\Admin_Dependencies;
*/
class GF_Admin_Script_Dependencies extends GF_Dependencies {
/**
* Items to enqueue globally in admin.
*
* @since 2.6
*
* @var string[]
*/
protected $items = array(
'gform_gravityforms_admin',
);
/**
* Enqueue the item by handle.
*
* @since 2.6
*
* @param $handle
*
* @return void
*/
protected function do_enqueue( $handle ) {
wp_enqueue_script( $handle );
}
/**
* Whether the global scripts should enqueue.
*
* @since 2.6
*
* @return bool
*/
protected function should_enqueue() {
/***
* The newer JavaScript added in 2.5 is now enqueued globally in the admin.
* We implemented this as we are now using code splitting to only inject JavaScript
* dynamically as it is needed, and to also allow our addons easy access to the core libraries
* we use.
*
* This filter allows users to make our admin scripts only load on Gravity Forms admin screens.
* Setting it to false may cause unexpected behavior/feature loss in some addons or core.
*
* @since 2.6.0
*
* @param bool true Load admin scripts globally?
*
* @return bool
*/
return apply_filters( 'gform_load_admin_scripts_globally', true );
}
}

View File

@@ -1,47 +0,0 @@
<?php
namespace Gravity_Forms\Gravity_Forms\Assets\Admin_Dependencies;
use Gravity_Forms\Gravity_Forms\Assets\GF_Dependencies;
use Gravity_Forms\Gravity_Forms\GF_Service_Container;
use Gravity_Forms\Gravity_Forms\GF_Service_Provider;
/**
* Class GF_Admin_Style_Dependencies
*
* @since 2.6
*
* @package Gravity_Forms\Gravity_Forms\Assets\Admin_Dependencies;
*/
class GF_Admin_Style_Dependencies extends GF_Dependencies {
/**
* Items to enqueue globally in admin.
*
* @since 2.6
*
* @var string[]
*/
protected $items = array(
'gform_common_css_utilities',
'gform_common_icons',
'gform_admin_icons',
'gform_admin_components',
'gform_admin_css_utilities',
);
/**
* Enqueue the item by handle.
*
* @since 2.6
*
* @param $handle
*
* @return void
*/
protected function do_enqueue( $handle ) {
wp_enqueue_style( $handle );
}
}

View File

@@ -1,84 +0,0 @@
<?php
namespace Gravity_Forms\Gravity_Forms\Assets;
class GF_Asset_Processor {
/**
* @var array $map - The Hash Map generated by our node scripts.
*/
private $map;
/**
* @var string $asset_path - The path to the js dist directory.
*/
private $asset_path;
/**
* Constructor
*
* @since 2.6
*
* @param array $map
* @param string $asset_path
*
* @return void
*/
public function __construct( $map, $asset_path ) {
$this->map = $map;
$this->asset_path = $asset_path;
}
/**
* Perform processing actions on assets.
*
* @since 2.6
*
* @return void
*/
public function process_assets() {
$this->process_versions();
}
/**
* Process the ver values for all of the registered scripts in order to append a
* file hash (if it exists) or the filemtime (if required).
*
* @since 2.6
*
* @return void
*/
private function process_versions() {
global $wp_scripts;
$registered = $wp_scripts->registered;
foreach( $registered as &$asset ) {
// Bail if not one of our assets.
if ( $asset->src && strpos( $asset->src, 'gravityforms/assets/js/dist' ) === false ) {
continue;
}
$basename = basename( $asset->src );
$path = sprintf( '%s/%s', $this->asset_path, $basename );
// Asset doesn't exist in hash_map, skip.
if ( ! array_key_exists( $basename, $this->map ) ) {
continue;
}
// The hash is either the value from our map, or the filemtime for dev.
$hash = defined( 'GF_DEV_TIME_AS_VER' ) && GF_DEV_TIME_AS_VER ?
filemtime( $path ) :
$this->map[ $basename ]['version'];
$asset->ver = $hash;
}
$wp_scripts->registered = $registered;
return;
}
}

View File

@@ -1,138 +0,0 @@
<?php
namespace Gravity_Forms\Gravity_Forms\Assets;
use Gravity_Forms\Gravity_Forms\Assets\Theme_Dependencies\GF_Theme_Script_Dependencies;
use Gravity_Forms\Gravity_Forms\GF_Service_Container;
use Gravity_Forms\Gravity_Forms\GF_Service_Provider;
use Gravity_Forms\Gravity_Forms\Assets\Admin_Dependencies\GF_Admin_Script_Dependencies;
use Gravity_Forms\Gravity_Forms\Assets\Admin_Dependencies\GF_Admin_Style_Dependencies;
/**
* Class GF_Asset_Service_Provider
*
* Service provider for assets.
*
* @package Gravity_Forms\Gravity_Forms\Merge_Tags;
*/
class GF_Asset_Service_Provider extends GF_Service_Provider {
const HASH_MAP = 'hash_map';
const ASSET_PROCESSOR = 'asset_processor';
const STYLE_DEPS = 'gf_global_style_deps';
const SCRIPT_DEPS = 'gf_global_script_deps';
const SCRIPT_DEPS_THEME = 'gf_global_script_deps_theme';
const SVG_OPTIONS = 'gf_svg_options';
private $plugin_dir;
public function __construct( $plugin_dir ) {
$this->plugin_dir = $plugin_dir;
}
/**
* Register services to the container.
*
* @since 2.6
*
* @param GF_Service_Container $container
*/
public function register( GF_Service_Container $container ) {
require_once( plugin_dir_path( __FILE__ ) . '/class-gf-asset-processor.php' );
require_once( plugin_dir_path( __FILE__ ) . '/class-gf-dependencies.php' );
require_once( plugin_dir_path( __FILE__ ) . '/admin-dependencies/class-gf-admin-script-dependencies.php' );
require_once( plugin_dir_path( __FILE__ ) . '/admin-dependencies/class-gf-admin-style-dependencies.php' );
require_once( plugin_dir_path( __FILE__ ) . '/theme-dependencies/class-gf-theme-script-dependencies.php' );
$container->add( self::HASH_MAP, function () {
if ( ! file_exists( \GFCommon::get_base_path() . '/assets/js/dist/assets.php' ) ) {
return array();
}
$map = require( \GFCommon::get_base_path() . '/assets/js/dist/assets.php' );
return rgar( $map, 'hash_map', array() );
} );
$container->add( self::ASSET_PROCESSOR, function () use ( $container ) {
$basepath = \GFCommon::get_base_path();
$asset_path = sprintf( '%s/assets/js/dist/', $basepath );
return new GF_Asset_Processor( $container->get( self::HASH_MAP ), $asset_path );
} );
$container->add( self::STYLE_DEPS, function () {
return new GF_Admin_Style_Dependencies();
} );
$container->add( self::SCRIPT_DEPS, function () {
return new GF_Admin_Script_Dependencies();
} );
$container->add( self::SCRIPT_DEPS_THEME, function () {
return new GF_Theme_Script_Dependencies();
} );
$this->svg_delivery( $container );
}
public function init( GF_Service_Container $container ) {
add_action( 'init', function () use ( $container ) {
$container->get( self::ASSET_PROCESSOR )->process_assets();
}, 9999 );
add_action( 'admin_enqueue_scripts', function () use ( $container ) {
$container->get( self::STYLE_DEPS )->enqueue();
$container->get( self::SCRIPT_DEPS )->enqueue();
// Styles and scripts required for the tooltips.
wp_enqueue_style( 'gform_font_awesome' );
wp_enqueue_script( 'gform_tooltip_init' );
} );
add_action( 'gform_enqueue_scripts', function () use ( $container ) {
$container->get( self::SCRIPT_DEPS_THEME )->enqueue();
} );
add_filter( 'gform_noconflict_styles', function ( $styles ) use ( $container ) {
return array_merge( $styles, $container->get( self::STYLE_DEPS )->get_items() );
}, 1 );
}
private function svg_delivery( GF_Service_Container $container ) {
$default_path = sprintf( '%s/assets/img/base', untrailingslashit( $this->plugin_dir ) );
/**
* Allows users to filter the path used to glob the available SVGs to use for display in themes.
*
* @since 2.7
*
* @param string $path The default orbital theme svg path within our plugin.
*
* @return string
*/
$svg_path = apply_filters( 'gform_svg_theme_path', $default_path );
$svgs = array();
foreach ( \GFCommon::glob( '*.svg', trailingslashit( $svg_path ) ) as $filename ) {
$key = pathinfo( $filename, PATHINFO_FILENAME );
$svgs[ $key ] = file_get_contents( $filename );
}
/**
* Allows users to filter the SVG options available to output in themes.
*
* @since 2.7
*
* @param array $svgs The current SVG options.
*
* @return array
*/
$svgs = apply_filters( 'gform_svg_theme_options', $svgs );
$container->add( self::SVG_OPTIONS, $svgs );
}
}

View File

@@ -1,55 +0,0 @@
<?php
/**
* Gravity Forms Abstract Asset
*
* Provides base functionality for enqueueable/printable assets.
*
* @since 2.5
* @package gravityforms
*/
if ( ! class_exists( 'GFForms' ) ) {
die();
}
/**
* Class GF_Asset
*/
abstract class GF_Asset {
/**
* @var string $handle
*/
protected $handle;
/**
* @var string $url
*/
protected $url;
/**
* GF_Asset constructor.
*
* @param string $handle
* @param string $url
*/
public function __construct( $handle, $url = '' ) {
$this->handle = $handle;
$this->url = $url;
}
/**
* Handle enqueueing the asset this class represents (e.g., using wp_enqueue_script() or wp_enqueue_style())
*
* @return void
*/
abstract public function enqueue_asset();
/**
* Handle printing the asset this class represents (e.g., using wp_print_scripts() or wp_print_styles())
*
* @return void
*/
abstract public function print_asset();
}

View File

@@ -1,66 +0,0 @@
<?php
namespace Gravity_Forms\Gravity_Forms\Assets;
abstract class GF_Dependencies {
/**
* Items to enqueue
*
* @since 2.6
*
* @var array
*/
protected $items = array();
/**
* The method for actually enqueueing the items.
*
* @since 2.6
*
* @param $handle
*
* @return mixed
*/
abstract protected function do_enqueue( $handle );
/**
* Get the dependency items.
*
* @since 2.6
*
* @return array
*/
public function get_items() {
return $this->items;
}
/**
* Enqueue the items.
*
* @since 2.6
*
* @param $items
*/
public function enqueue() {
if ( ! $this->should_enqueue() ) {
return;
}
foreach ( $this->items as $handle ) {
$this->do_enqueue( $handle );
}
}
/**
* Override to determine whether the assets outlined should be enqueued.
*
* @since 2.6
*
* @return bool
*/
protected function should_enqueue() {
return true;
}
}

View File

@@ -1,72 +0,0 @@
<?php
/**
* Gravity Forms Script Asset
*
* @since 2.5
* @package gravityforms
*/
if ( ! class_exists( 'GFForms' ) ) {
die();
}
/**
* Class GF_Script_Asset
*/
class GF_Script_Asset extends GF_Asset {
/**
* The data for any localized information.
*
* @since 2.5
*
* @var array $localize_data
*/
private $localize_data = array();
/**
* Localize data to this script.
*
* @since 2.5
*
* @param string $object_name
* @param array $data
*
* @return void
*/
public function add_localize_data( $object_name, $data ) {
$this->localize_data[ $object_name ] = $data;
}
/**
* Enqueue the asset.
*
* @since 2.5
*
* @return void
*/
public function enqueue_asset() {
wp_enqueue_script( $this->handle, $this->url );
if ( empty( $this->localize_data ) ) {
return;
}
foreach ( $this->localize_data as $object_name => $data ) {
wp_localize_script( $this->handle, $object_name, $data );
}
}
/**
* Print the asset.
*
* @since 2.5
*
* @return void
*/
public function print_asset() {
$this->enqueue_asset();
wp_print_scripts( $this->handle );
}
}

View File

@@ -1,40 +0,0 @@
<?php
/**
* Gravity Forms Style Asset
*
* @since 2.5
* @package gravityforms
*/
if ( ! class_exists( 'GFForms' ) ) {
die();
}
/**
* Class GF_Style_Asset
*/
class GF_Style_Asset extends GF_Asset {
/**
* Enqueue the asset.
*
* @since 2.5
*
* @return void
*/
public function enqueue_asset() {
wp_enqueue_style( $this->handle, $this->url );
}
/**
* Print the asset.
*
* @since 2.5
*
* @return void
*/
public function print_asset() {
$this->enqueue_asset();
wp_print_styles( $this->handle );
}
}

View File

@@ -1,2 +0,0 @@
<?php
//Nothing to see here

View File

@@ -1,42 +0,0 @@
<?php
namespace Gravity_Forms\Gravity_Forms\Assets\Theme_Dependencies;
use Gravity_Forms\Gravity_Forms\Assets\GF_Dependencies;
use Gravity_Forms\Gravity_Forms\GF_Service_Container;
use Gravity_Forms\Gravity_Forms\GF_Service_Provider;
/**
* Class GF_Theme_Script_Dependencies
*
* @since 2.6
*
* @package Gravity_Forms\Gravity_Forms\Assets\Theme_Dependencies;
*/
class GF_Theme_Script_Dependencies extends GF_Dependencies {
/**
* Items to enqueue globally in admin.
*
* @since 2.6
*
* @var string[]
*/
protected $items = array(
'gform_gravityforms_theme',
);
/**
* Enqueue the item by handle.
*
* @since 2.6
*
* @param $handle
*
* @return void
*/
protected function do_enqueue( $handle ) {
wp_enqueue_script( $handle );
}
}

View File

@@ -1,100 +0,0 @@
<?php
/**
* Service provider for async (background) processors.
*
* @package Gravity_Forms\Gravity_Forms
*/
namespace Gravity_Forms\Gravity_Forms\Async;
use Gravity_Forms\Gravity_Forms\GF_Service_Container;
use Gravity_Forms\Gravity_Forms\GF_Service_Provider;
use Gravity_Forms\Gravity_Forms\Telemetry\GF_Telemetry_Processor;
use GFForms;
use GF_Background_Process;
use GF_Background_Upgrader;
use GF_Feed_Processor;
if ( ! class_exists( 'GFForms' ) ) {
die();
}
/**
* Class GF_Background_Processing_Service_Provider
*
* @since 2.6.9
*/
class GF_Background_Process_Service_Provider extends GF_Service_Provider {
const UPGRADER = 'upgrade_processor';
const FEEDS = 'feeds_processor';
const NOTIFICATIONS = 'notifications_processor';
const TELEMETRY = 'telemetry_processor';
/**
* The names and classes of the async (background) processors.
*
* @since 2.6.9
*
* @var string[]
*/
protected $processors = array(
self::UPGRADER => GF_Background_Upgrader::class,
self::FEEDS => GF_Feed_Processor::class,
self::NOTIFICATIONS => GF_Notifications_Processor::class,
self::TELEMETRY => GF_Telemetry_Processor::class,
);
/**
* Initializing the processors and adding them to the container as services.
*
* @since 2.6.9
*
* @param GF_Service_Container $container
*/
public function register( GF_Service_Container $container ) {
GFForms::init_background_upgrader();
require_once GF_PLUGIN_DIR_PATH . 'includes/addon/class-gf-feed-processor.php';
require_once GF_PLUGIN_DIR_PATH . 'includes/async/class-gf-notifications-processor.php';
require_once GF_PLUGIN_DIR_PATH . 'includes/telemetry/class-gf-telemetry-processor.php';
foreach ( $this->processors as $name => $class ) {
$container->add( $name, function () use ( $name, $class ) {
if ( $name === self::UPGRADER ) {
return GFForms::$background_upgrader;
}
$callback = array( $class, 'get_instance' );
if ( is_callable( $callback ) ) {
return call_user_func( $callback );
}
return new $class();
} );
}
}
/**
* Initializing hooks.
*
* @since 2.6.9
*
* @param GF_Service_Container $container
*/
public function init( GF_Service_Container $container ) {
$processors = array_keys( $this->processors );
add_action( 'gform_uninstalling', function () use ( $processors, $container ) {
foreach ( $processors as $name ) {
/**
* @var GF_Background_Process $processor
*/
$processor = $container->get( $name );
$processor->clear_scheduled_events();
$processor->clear_queue( true );
$processor->unlock_process();
}
} );
}
}

View File

@@ -1,135 +0,0 @@
<?php
namespace Gravity_Forms\Gravity_Forms\Async;
use GF_Background_Process;
use GFCommon;
use GFAPI;
if ( ! class_exists( 'GFForms' ) ) {
die();
}
if ( ! class_exists( 'GF_Background_Process' ) ) {
require_once GF_PLUGIN_DIR_PATH . 'includes/libraries/gf-background-process.php';
}
/**
* GF_Notifications_Processor Class.
*
* @since 2.6.9
*/
class GF_Notifications_Processor extends GF_Background_Process {
/**
* The action name.
*
* @since 2.6.9
*
* @var string
*/
protected $action = 'gf_notifications_processor';
/**
* Processes the task.
*
* @since 2.6.9
*
* @param array $item The task arguments.
*
* @return bool
*/
protected function task( $item ) {
$notifications = rgar( $item, 'notifications' );
if ( empty( $notifications ) || ! is_array( $notifications ) ) {
return false;
}
$entry = GFAPI::get_entry( rgar( $item, 'entry_id' ) );
if ( is_wp_error( $entry ) ) {
GFCommon::log_debug( __METHOD__ . sprintf( '(): Aborting; Entry #%d not found.', rgar( $item, 'entry_id' ) ) );
return false;
}
$form = GFAPI::get_form( rgar( $item, 'form_id' ) );
if ( empty( $form ) ) {
GFCommon::log_debug( __METHOD__ . sprintf( '(): Aborting; Form #%d not found.', rgar( $item, 'form_id' ) ) );
return false;
}
$form = $this->filter_form( $form, $entry );
$event = rgar( $item, 'event', 'form_submission' );
$data = rgar( $item, 'data' );
if ( ! is_array( $data ) ) {
$data = array();
}
/**
* Allows custom actions to be performed before notifications are sent asynchronously.
*
* @since 2.7.1
*
* @param string $event The event being processed.
* @param array $notifications An array containing the IDs of the notifications being processed.
* @param array $form The form being processed.
* @param array $entry The entry being processed.
* @param array $data An array of data which can be used in the notifications via the generic {object:property} merge tag. Defaults to empty array.
*/
do_action( 'gform_pre_process_async_notifications', $event, $notifications, $form, $entry, $data );
GFCommon::send_notifications( $notifications, $form, $entry, true, $event, $data );
/**
* Allows custom actions to be performed after notifications are sent asynchronously.
*
* @since 2.7.1
*
* @param string $event The event being processed.
* @param array $notifications An array containing the IDs of the notifications being processed.
* @param array $form The form being processed.
* @param array $entry The entry being processed.
* @param array $data An array of data which can be used in the notifications via the generic {object:property} merge tag. Defaults to empty array.
*/
do_action( 'gform_post_process_async_notifications', $event, $notifications, $form, $entry, $data );
return false;
}
/**
* Determines if async (background) processing of notifications is enabled.
*
* @since 2.7.1
*
* @param array $notifications An array containing the IDs of the notifications to be sent.
* @param array $form The form being processed.
* @param array $entry The entry being processed.
* @param string $event The event being processed.
* @param array $data An array of data which can be used in the notifications via the generic {object:property} merge tag. Defaults to empty array.
*
* @return bool
*/
public function is_enabled( $notifications, $form, $entry, $event = 'form_submission', $data = array() ) {
$form_id = absint( rgar( $form, 'id' ) );
$is_enabled = false;
/**
* Allows async (background) processing of notifications to be enabled or disabled.
*
* @since 2.6.9
*
* @param bool $is_enabled Is async (background) processing of notifications enabled? Default is false.
* @param string $event The event the notifications are to be sent for.
* @param array $notifications An array containing the IDs of the notifications to be sent.
* @param array $form The form currently being processed.
* @param array $entry The entry currently being processed.
* @param array $data An array of data which can be used in the notifications via the generic {object:property} merge tag. Defaults to empty array.
*/
return gf_apply_filters( array(
'gform_is_asynchronous_notifications_enabled',
$form_id,
), $is_enabled, $event, $notifications, $form, $entry, $data );
}
}

View File

@@ -1,28 +0,0 @@
<?php
namespace Gravity_Forms\Gravity_Forms\Blocks;
/**
* Gravity Forms Block Attributes class.
*
* @since 2.7.4
*
* Class GF_Block_Attributes
*/
class GF_Block_Attributes {
public function store( $attributes ) {
add_filter( 'gform_form_block_attribute_values', function( $attr ) use ( $attributes ) {
$form_id = rgar( $attributes, 'formId', 0 );
if ( ! array_key_exists( $form_id, $attr ) ) {
$attr[ $form_id ] = array();
}
$attr[ $form_id ][] = $attributes;
return $attr;
} );
}
}

View File

@@ -1,251 +0,0 @@
<?php
// If Gravity Forms Block Manager is not available, do not run.
if ( ! class_exists( 'GF_Blocks' ) || ! defined( 'ABSPATH' ) ) {
exit;
}
class GF_Block_Form extends GF_Block {
/**
* Contains an instance of this block, if available.
*
* @since 2.4.10
* @var GF_Block $_instance If available, contains an instance of this block.
*/
private static $_instance = null;
/**
* Block type.
*
* @since 2.4.10
* @var string
*/
public $type = 'gravityforms/form';
/**
* Handle of primary block script.
*
* @since 2.4.10
* @var string
*/
public $script_handle = 'gform_editor_block_form';
/**
* Handle of primary block style.
*
* @since 2.5.6
* @var string
*/
public $style_handle = 'gform_editor_block_form';
public function __construct() {
$this->assign_attributes();
}
private function assign_attributes() {
$default_attributes = GFForms::get_service_container()->get( \Gravity_Forms\Gravity_Forms\Blocks\GF_Blocks_Service_Provider::FORM_BLOCK_ATTRIBUTES );
$attributes = apply_filters( 'gform_form_block_attributes', $default_attributes );
array_walk( $attributes, function ( &$value ) {
$value = array( 'type' => $value['type'] );
} );
$this->attributes = $attributes;
}
/**
* Get instance of this class.
*
* @since 2.4.10
*
* @return GF_Block_Form
*/
public static function get_instance() {
if ( null === self::$_instance ) {
self::$_instance = new self();
}
return self::$_instance;
}
// # SCRIPT / STYLES -----------------------------------------------------------------------------------------------
public function register_block_assets() {
parent::register_block_assets();
if ( function_exists( 'wp_enqueue_block_style' ) && is_admin() ) {
wp_enqueue_block_style( $this->type, array( 'handle' => 'gravity_forms_theme_reset' ) );
wp_enqueue_block_style( $this->type, array( 'handle' => 'gravity_forms_theme_foundation' ) );
wp_enqueue_block_style( $this->type, array( 'handle' => 'gravity_forms_theme_framework' ) );
wp_enqueue_block_style( $this->type, array( 'handle' => 'gravity_forms_orbital_theme' ) );
}
}
/**
* Register scripts for block.
*
* @since 2.4.10
*
* @return array
*/
public function scripts() {
return array();
}
/**
* Localize Form block script.
*
* @since 2.4.10
*
* @param array $script Script arguments.
*/
public function localize_script( $script = array() ) {
wp_localize_script(
$script['handle'],
'gform_block_form',
array(
'adminURL' => admin_url( 'admin.php' ),
'forms' => $this->get_forms(),
'preview' => GFCommon::get_base_url() . '/images/gf_block_preview.svg',
)
);
if ( function_exists( 'wp_set_script_translations' ) ) {
wp_set_script_translations( $script['handle'], 'gravityforms', GFCommon::get_base_path() . '/languages' );
}
}
/**
* Register styles for block.
*
* @since 2.4.10
*
* @return array
*/
public function styles() {
// Prepare styling dependencies.
$deps = array( 'wp-edit-blocks' );
/**
* Allows users to disable all CSS files from being loaded on the Front End.
*
* @since 2.8
*
* @param boolean Whether to disable css.
*/
$disable_css = apply_filters( 'gform_disable_css', get_option( 'rg_gforms_disable_css' ) );
// Add Gravity Forms styling if CSS is enabled.
if ( ! $disable_css ) {
$deps = array_merge( $deps, array( 'gform_basic', 'gforms_formsmain_css', 'gforms_ready_class_css', 'gforms_browsers_css', 'gform_theme' ) );
/**
* Allows users to disable the main theme.css file from being loaded on the Front End.
*
* @since 2.5-beta-3
*
* @param boolean Whether to disable the theme css.
*/
$disable_theme_css = apply_filters( 'gform_disable_form_theme_css', false );
if ( ! $disable_theme_css ) {
$deps[] = 'gform_theme';
}
}
$dev_min = defined( 'GF_SCRIPT_DEBUG' ) && GF_SCRIPT_DEBUG ? '' : '.min';
return array(
array(
'handle' => $this->style_handle,
'src' => GFCommon::get_base_url() . "/assets/css/dist/blocks{$dev_min}.css",
'deps' => $deps,
'version' => defined( 'GF_SCRIPT_DEBUG' ) && GF_SCRIPT_DEBUG ? filemtime( GFCommon::get_base_path() . "/assets/css/dist/blocks{$dev_min}.css" ) : GFForms::$version,
),
);
}
// # BLOCK RENDER -------------------------------------------------------------------------------------------------
/**
* Display block contents on frontend.
*
* @since 2.4.10
*
* @param array $attributes Block attributes.
*
* @return string
*/
public function render_block( $attributes = array() ) {
GFForms::get_service_container()->get( 'block_attributes' )->store( $attributes );
// Prepare variables.
$form_id = rgar( $attributes, 'formId' ) ? $attributes['formId'] : false;
$title = isset( $attributes['title'] ) ? $attributes['title'] : true;
$description = isset( $attributes['description'] ) ? $attributes['description'] : true;
$ajax = isset( $attributes['ajax'] ) ? $attributes['ajax'] : false;
$tabindex = isset( $attributes['tabindex'] ) ? intval( $attributes['tabindex'] ) : 0;
$field_values = isset( $attributes['fieldValues'] ) ? $attributes['fieldValues'] : '';
// If form ID was not provided or form does not exist, return.
if ( ! $form_id || ( $form_id && ! GFAPI::get_form( $form_id ) ) ) {
return '';
}
// Use Gravity Forms function for REST API requests.
if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
// Start output buffering.
ob_start();
// Prepare field values.
if ( ! empty( $field_values ) ) {
$field_values = str_replace( '&#038;', '&', $field_values );
parse_str( $field_values, $field_value_array );
$field_values = stripslashes_deep( $field_value_array );
}
// Get form output string.
$form_string = gravity_form( $form_id, $title, $description, false, $field_values, $ajax, $tabindex, false );
// Get output buffer contents.
$buffer_contents = ob_get_contents();
ob_end_clean();
// Return buffer contents with form string.
return $buffer_contents . $form_string;
}
// Encode field values.
$field_values = htmlspecialchars_decode( $field_values );
$field_values = str_replace( array( '&#038;', '&#091;', '&#093;' ), array( '&', '[', ']' ), $field_values );
parse_str( $field_values, $field_value_array ); //parsing query string like string for field values and placing them into an associative array
$field_values = stripslashes_deep( $field_value_array );
// If no field values are set, set field values to an empty string
if ( empty( $field_values ) ) {
$field_values = '';
}
return gravity_form( $form_id, $title, $description, false, $field_values, $ajax, $tabindex, false );
}
}
// Register block.
if ( true !== ( $registered = GF_Blocks::register( GF_Block_Form::get_instance() ) ) && is_wp_error( $registered ) ) {
// Log that block could not be registered.
GFCommon::log_error( 'Unable to register block; ' . $registered->get_error_message() );
}

View File

@@ -1,369 +0,0 @@
<?php
// If Gravity Forms Block Manager is not available, do not run.
if ( ! class_exists( 'GF_Blocks' ) || ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Base Gravity Forms Block class.
*
* @since 2.4.10
*
* Class GF_Block
*/
class GF_Block {
/**
* Contains an instance of this block, if available.
*
* @since 2.4.10
* @var GF_Block $_instance If available, contains an instance of this block.
*/
private static $_instance = null;
/**
* Block type.
*
* @since 2.4.10
* @var string
*/
public $type = '';
/**
* Handle of primary block editor script.
*
* @since 2.4.10
* @var string
*/
public $script_handle = '';
/**
* Handle of primary block editor style.
*
* @since 2.5.6
* @var string
*/
public $style_handle = '';
/**
* Handle of primary block FE script.
*
* @since 2.4.10
* @var string
*/
public $fe_script_handle = '';
/**
* Handle of primary block FE style.
*
* @since 2.5.6
* @var string
*/
public $fe_style_handle = '';
/**
* Block attributes.
*
* @since 2.4.10
* @var array
*/
public $attributes = array();
/**
* Register block type.
* Enqueue editor assets.
*
* @since 2.4.10
*
* @uses GF_Block::register_block_type()
*/
public function init() {
$this->register_block_type();
$this->register_block_assets();
add_action( 'gform_post_enqueue_scripts', array( $this, 'post_enqueue_scripts' ), 10, 3 );
}
// # BLOCK REGISTRATION --------------------------------------------------------------------------------------------
/**
* Get block type.
*
* @since 2.4.10
*
* @return string
*/
public function get_type() {
return $this->type;
}
/**
* Register block with WordPress.
*
* @since 2.4.10
*/
public function register_block_type() {
register_block_type( $this->get_type(), $this->get_block_properties() );
}
/**
* Get an array representing the properties for this block. Can be overriden by inheriting
* classes in order to provide more/fewer/different properties.
*
* @since 2.5.6
*
* @return array
*/
protected function get_block_properties() {
return array(
'render_callback' => array( $this, 'render_block' ),
'editor_script' => $this->script_handle,
'editor_style' => $this->style_handle,
'attributes' => $this->attributes,
'script' => $this->fe_script_handle,
'style' => $this->fe_style_handle,
);
}
/**
* Enqueue/register the block's assets upon init
*
* @since 2.5.6
*
* @return void
*/
public function register_block_assets() {
add_action( 'enqueue_block_editor_assets', array( $this, 'register_scripts' ) );
add_action( 'enqueue_block_editor_assets', array( $this, 'register_styles' ) );
}
/**
* Checks allowed blocks for Gravity forms blocks to only enqueue block editor assets when necessary.
*
* @since 2.4.18
*
* @deprecated since 2.5.6. See GF_Block::register_block_assets()
*
* @param bool|array $allowed_block_types Array of block type slugs, or boolean to enable/disable all.
*
* @return bool|array
*/
public function check_allowed_blocks( $allowed_block_types ) {
// Only enqueue block editor assets if all blocks are allowed or if the current block type is an allowed block.
if ( $allowed_block_types === true || ( is_array( $allowed_block_types ) && in_array( $this->get_type(), $allowed_block_types ) ) ) {
add_action( 'enqueue_block_editor_assets', array( $this, 'register_scripts' ) );
add_action( 'enqueue_block_editor_assets', array( $this, 'register_styles' ) );
}
return $allowed_block_types;
}
// # SCRIPT ENQUEUEING ---------------------------------------------------------------------------------------------
/**
* Enqueue block scripts.
*
* @since 2.4.10
*
* @uses GF_Block::scripts()
*/
public function register_scripts() {
// Get registered scripts.
$scripts = $this->scripts();
// If no scripts are registered, return.
if ( empty( $scripts ) ) {
return;
}
// Loop through scripts.
foreach ( $scripts as $script ) {
// Prepare parameters.
$src = isset( $script['src'] ) ? $script['src'] : false;
$deps = isset( $script['deps'] ) ? $script['deps'] : array();
$version = isset( $script['version'] ) ? $script['version'] : false;
$in_footer = isset( $script['in_footer'] ) ? $script['in_footer'] : false;
// Enqueue script.
if ( $this->script_handle === $script['handle'] ) {
// Support for the editor_style property, if a style_handle is defined. No need to enqueue.
wp_register_script( $script['handle'], $src, $deps, $version, $in_footer );
} else {
// style_handle isn't defined, or this is an additional style. Enqueue it manually.
wp_enqueue_script( $script['handle'], $src, $deps, $version, $in_footer );
}
// Localize script.
if ( rgar( $script, 'strings' ) ) {
wp_localize_script( $script['handle'], $script['handle'] . '_strings', $script['strings'] );
}
// Run script callback.
if ( rgar( $script, 'callback' ) && is_callable( $script['callback'] ) ) {
call_user_func( $script['callback'], $script );
}
}
}
/**
* Enqueue scripts
*
* @depecated since 2.5.6. Use ::register_scripts() instead.
*
* @return void
*/
public function enqueue_scripts() {
$this->register_scripts();
}
/**
* Override this function to provide a list of scripts to be enqueued.
* Following is an example of the array that is expected to be returned by this function:
* <pre>
* <code>
*
* array(
* array(
* 'handle' => 'super_signature_script',
* 'src' => $this->get_base_url() . '/super_signature/ss.js',
* 'version' => $this->_version,
* 'deps' => array( 'jquery'),
* 'callback' => array( $this, 'localize_scripts' ),
* 'strings' => array(
* // Accessible in JavaScript using the global variable "[script handle]_strings"
* 'stringKey1' => __( 'The string', 'gravityforms' ),
* 'stringKey2' => __( 'Another string.', 'gravityforms' )
* )
* )
* );
*
* </code>
* </pre>
*
* @since 2.4.10
*
* @return array
*/
public function scripts() {
return array();
}
// # STYLE ENQUEUEING ----------------------------------------------------------------------------------------------
/**
* Enqueue block styles.
*
* @since 2.4.10
*/
public function register_styles() {
// Get registered styles.
$styles = $this->styles();
// If no styles are registered, return.
if ( empty( $styles ) ) {
return;
}
// Loop through styles.
foreach ( $styles as $style ) {
// Prepare parameters.
$src = isset( $style['src'] ) ? $style['src'] : false;
$deps = isset( $style['deps'] ) ? $style['deps'] : array();
$version = isset( $style['version'] ) ? $style['version'] : false;
$media = isset( $style['media'] ) ? $style['media'] : 'all';
if ( $this->style_handle === $style['handle'] ) {
// Support for the editor_style property, if a style_handle is defined. No need to enqueue.
wp_register_style( $style['handle'], $src, $deps, $version, $media );
} else {
// style_handle isn't defined, or this is an additional style. Enqueue it manually.
wp_enqueue_style( $style['handle'], $src, $deps, $version, $media );
}
}
}
/**
* Enqueue styles
*
* @depecated since 2.5.6. Use ::register_styles() instead.
*
* @return void
*/
public function enqueue_styles() {
$this->register_styles();
}
/**
* Override this function to provide a list of styles to be enqueued.
* See scripts() for an example of the format expected to be returned.
*
* @since 2.4.10
*
* @return array
*/
public function styles() {
return array();
}
// # BLOCK RENDER -------------------------------------------------------------------------------------------------
/**
* Display block contents on frontend.
*
* @since 2.4.10
*
* @param array $attributes Block attributes.
*
* @return string
*/
public function render_block( $attributes = array() ) {
return '';
}
/**
* Override to perform additional actions when scripts/styles are enqueued on the wp_enqueue_scripts hook.
*
* @since 2.4.18
*
* @param array $found_forms An array of found forms using the form ID as the key to the ajax status.
* @param array $found_blocks An array of found GF blocks.
* @param WP_Post $post The post which was processed.
*/
public function post_enqueue_scripts( $found_forms, $found_blocks, $post ) {
}
}

View File

@@ -1,230 +0,0 @@
<?php
namespace Gravity_Forms\Gravity_Forms\Blocks;
use Gravity_Forms\Gravity_Forms\Config\GF_Config_Service_Provider;
use Gravity_Forms\Gravity_Forms\Blocks\Config\GF_Blocks_Config;
use Gravity_Forms\Gravity_Forms\Blocks\GF_Block_Attributes;
use Gravity_Forms\Gravity_Forms\GF_Service_Container;
use Gravity_Forms\Gravity_Forms\GF_Service_Provider;
use GFFormDisplay;
use GFCommon;
/**
* Class GF_Blocks_Service_Provider
*
* Service provider for the Blocks Service.
*
* @package Gravity_Forms\Gravity_Forms\Blocks;
*/
class GF_Blocks_Service_Provider extends GF_Service_Provider {
// Configs
const BLOCKS_CONFIG = 'blocks_config';
// Attributes
const FORM_BLOCK_ATTRIBUTES = 'form_block_attributes';
const BLOCK_ATTRIBUTES = 'block_attributes';
/**
* Array mapping config class names to their container ID.
*
* @since
*
* @var string[]
*/
protected $configs = array(
self::BLOCKS_CONFIG => GF_Blocks_Config::class,
);
/**
* Register services to the container.
*
* @since
*
* @param GF_Service_Container $container
*/
public function register( GF_Service_Container $container ) {
require_once( plugin_dir_path( __FILE__ ) . 'class-gf-block-attributes.php' );
require_once( plugin_dir_path( __FILE__ ) . '/config/class-gf-blocks-config.php' );
$container->add( self::FORM_BLOCK_ATTRIBUTES, function () {
require_once( GFCommon::get_base_path() . '/form_display.php' );
$global_styles = GFFormDisplay::validate_form_styles( apply_filters( 'gform_default_styles', false ) );
return array(
'formId' =>
array(
'type' => 'string',
),
'title' =>
array(
'type' => 'boolean',
'default' => true,
),
'description' =>
array(
'type' => 'boolean',
'default' => true,
),
'ajax' =>
array(
'type' => 'boolean',
'default' => false,
),
'tabindex' =>
array(
'type' => 'string',
),
'fieldValues' =>
array(
'type' => 'string',
),
'formPreview' =>
array(
'type' => 'boolean',
'default' => true,
),
'imgPreview' =>
array(
'type' => 'boolean',
'default' => false,
),
'theme' =>
array(
'type' => 'string',
'default' => '',
),
'inputSize' =>
array(
'type' => 'string',
'default' => rgar( $global_styles, 'inputSize' ) ? $global_styles['inputSize'] : 'md',
),
'inputBorderRadius' =>
array(
'type' => 'string',
'default' => rgar( $global_styles, 'inputBorderRadius' ) ? $global_styles['inputBorderRadius'] : 3,
),
'inputBorderColor' =>
array(
'type' => 'string',
'default' => rgar( $global_styles, 'inputBorderColor' ) ? $global_styles['inputBorderColor'] : '#686e77',
),
'inputBackgroundColor' =>
array(
'type' => 'string',
'default' => rgar( $global_styles, 'inputBackgroundColor' ) ? $global_styles['inputBackgroundColor'] : '#fff',
),
'inputColor' =>
array(
'type' => 'string',
'default' => rgar( $global_styles, 'inputColor' ) ? $global_styles['inputColor'] : '#112337',
),
'inputPrimaryColor' =>
array(
'type' => 'string',
// Setting this to empty allows us to set this to what the appropriate default
// should be from within the block. When empty, it defaults to:
// buttonPrimaryBackgroundColor
'default' => rgar( $global_styles, 'inputPrimaryColor' ) ? $global_styles['inputPrimaryColor'] : '', // #204ce5
),
'labelFontSize' =>
array(
'type' => 'string',
'default' => rgar( $global_styles, 'labelFontSize' ) ? $global_styles['labelFontSize'] : 14,
),
'labelColor' =>
array(
'type' => 'string',
'default' => rgar( $global_styles, 'labelColor' ) ? $global_styles['labelColor'] : '#112337',
),
'descriptionFontSize' =>
array(
'type' => 'string',
'default' => rgar( $global_styles, 'descriptionFontSize' ) ? $global_styles['descriptionFontSize'] : 13,
),
'descriptionColor' =>
array(
'type' => 'string',
'default' => rgar( $global_styles, 'descriptionColor' ) ? $global_styles['descriptionColor'] : '#585e6a',
),
'buttonPrimaryBackgroundColor' =>
array(
'type' => 'string',
'default' => rgar( $global_styles, 'buttonPrimaryBackgroundColor' ) ? $global_styles['buttonPrimaryBackgroundColor'] : '#204ce5',
),
'buttonPrimaryColor' =>
array(
'type' => 'string',
'default' => rgar( $global_styles, 'buttonPrimaryColor' ) ? $global_styles['buttonPrimaryColor'] : '#fff',
),
);
} );
$this->add_configs( $container );
$this->block_attributes( $container );
}
/**
* Initialize any actions or hooks.
*
* @since
*
* @param GF_Service_Container $container
*
* @return void
*/
public function init( GF_Service_Container $container ) {
add_action( 'gform_post_enqueue_scripts', function( $found_forms, $found_blocks, $post ) use ( $container ) {
foreach( $found_blocks as $block ) {
$attributes = $block['attrs'];
$container->get( self::BLOCK_ATTRIBUTES )->store( $attributes );
}
}, -10, 3 );
}
/**
* For each config defined in $configs, instantiate and add to container.
*
* @since
*
* @param GF_Service_Container $container
*
* @return void
*/
private function add_configs( GF_Service_Container $container ) {
foreach ( $this->configs as $name => $class ) {
$container->add( $name, function () use ( $container, $class ) {
if ( $class == GF_Blocks_Config::class ) {
return new $class( $container->get( GF_Config_Service_Provider::DATA_PARSER ), $container->get( self::FORM_BLOCK_ATTRIBUTES ) );
}
return new $class( $container->get( GF_Config_Service_Provider::DATA_PARSER ) );
} );
$container->get( GF_Config_Service_Provider::CONFIG_COLLECTION )->add_config( $container->get( $name ) );
}
}
/**
* Register Block services.
*
* @since 2.7.4
*
* @param GF_Service_Container $container
*
* @return void
*/
private function block_attributes( GF_Service_Container $container ) {
$container->add( self::BLOCK_ATTRIBUTES, function () use ( $container ) {
return new GF_Block_Attributes();
} );
}
}

View File

@@ -1,89 +0,0 @@
<?php
defined( 'ABSPATH' ) or die();
// Load core Block class.
require_once( plugin_dir_path( __FILE__ ) . 'class-gf-block.php' );
/**
* Handles management of Gravity Forms editor blocks.
*
* @since 2.4.10
*
* Class GF_Blocks
*/
class GF_Blocks {
/**
* Registered Gravity Forms editor blocks.
*
* @since 2.4.10
* @var GF_Block[]
*/
private static $_blocks = array();
/**
* Register a block type.
*
* @since 2.4.10
*
* @param GF_Block $block Block class.
*
* @return bool|WP_Error
*/
public static function register( $block ) {
if ( ! is_subclass_of( $block, 'GF_Block' ) ) {
return new WP_Error( 'block_not_subclass', 'Must be a subclass of GF_Block' );
}
// Get block type.
$block_type = $block->get_type();
if ( empty( $block_type ) ) {
return new WP_Error( 'block_type_undefined', 'The type must be set' );
}
if ( isset( self::$_blocks[ $block_type ] ) ) {
return new WP_Error( 'block_already_registered', 'Block type already registered: ' . $block_type );
}
// Register block.
self::$_blocks[ $block_type ] = $block;
// Initialize block.
call_user_func( array( $block, 'init' ) );
return true;
}
/**
* Get instance of block.
*
* @since 2.4.10
*
* @param string $block_type Block type.
*
* @return GF_Block|bool
*/
public static function get( $block_type ) {
return isset( self::$_blocks[ $block_type ] ) ? self::$_blocks[ $block_type ] : false;
}
/**
* Returns an array of registered block types.
*
* @since 2.4.18
*
* @return array
*/
public static function get_all_types() {
return array_keys( self::$_blocks );
}
}
new GF_Blocks();

View File

@@ -1,98 +0,0 @@
<?php
namespace Gravity_Forms\Gravity_Forms\Blocks\Config;
use GFSettings;
use Gravity_Forms\Gravity_Forms\Config\GF_Config;
use Gravity_Forms\Gravity_Forms\Config\GF_Config_Data_Parser;
use \GFCommon;
use \GFAPI;
use \GFFormDisplay;
/**
* Config items for Blocks.
*
* @since
*/
class GF_Blocks_Config extends GF_Config {
protected $name = 'gform_admin_config';
protected $script_to_localize = 'gform_gravityforms_admin_vendors';
protected $attributes = array();
public function __construct( GF_Config_Data_Parser $parser, array $attributes ) {
parent::__construct( $parser );
$this->attributes = $attributes;
}
public function should_enqueue() {
return GFCommon::is_block_editor_page();
}
/**
* Get list of forms for Block control.
*
* @since 2.4.10
*
* @return array
*/
public function get_forms() {
// Initialize forms array.
$forms = array();
// Load GFFormDisplay class.
if ( ! class_exists( 'GFFormDisplay' ) ) {
require_once GFCommon::get_base_path() . '/form_display.php';
}
// Get form objects.
$form_objects = GFAPI::get_forms( true, false, 'title', 'ASC' );
// Loop through forms, add conditional logic check.
foreach ( $form_objects as $form ) {
$forms[] = array(
'id' => $form['id'],
'title' => $form['title'],
'hasConditionalLogic' => GFFormDisplay::has_conditional_logic( $form ),
'isLegacyMarkup' => GFCommon::is_legacy_markup_enabled( $form ),
);
}
/**
* Modify the list of available forms displayed in the Form block.
*
* @since 2.4.23
*
* @param array $forms A collection of active forms on site.
*/
return apply_filters( 'gform_block_form_forms', $forms );
}
/**
* Config data.
*
* @return array[]
*/
public function data() {
$attributes = apply_filters( 'gform_form_block_attributes', $this->attributes );
$orbital_default = GFSettings::is_orbital_default();
return array(
'gravityforms/form' => array(
'data' => array(
'attributes' => $attributes,
'adminURL' => admin_url( 'admin.php' ),
'forms' => $this->get_forms(),
'preview' => GFCommon::get_base_url() . '/images/gf_block_preview.svg',
'orbitalDefault' => $orbital_default,
'styles' => array(
'defaults' => \GFForms::get_service_container()->get( \Gravity_Forms\Gravity_Forms\Form_Display\GF_Form_Display_Service_Provider::BLOCK_STYLES_DEFAULTS ),
),
),
),
);
}
}

View File

@@ -1,104 +0,0 @@
<?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;
}
if ( ! class_exists( 'GF_Background_Process' ) ) {
require_once GF_PLUGIN_DIR_PATH . 'includes/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();
}
}

View File

@@ -1,209 +0,0 @@
<?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}." );
$permission_granted = self::validate_download( $form_id, $field_id, $file, $hash );
if ( has_filter( 'gform_permission_granted_pre_download' ) ) {
GFCommon::log_debug( __METHOD__ . '(): Executing functions hooked to gform_permission_granted_pre_download.' );
}
/**
* Allow custom logic to be used to determine if the file can be accessed.
*
* @since 2.4.3.2
*
* @param bool $permission_granted Indicates if access to the file has been granted. Default is the result of the hash validation.
* @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.
*/
$permission_granted = apply_filters( 'gform_permission_granted_pre_download', $permission_granted, $form_id, $field_id );
if ( $permission_granted ) {
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;
}
if ( has_filter( 'gform_require_login_pre_download' ) ) {
GFCommon::log_debug( __METHOD__ . '(): Executing functions hooked to gform_require_login_pre_download.' );
}
/**
* 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="' . wp_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();
}
}

View File

@@ -1,351 +0,0 @@
<?php
/**
* Adds integration with osDXP.
*
* @since 2.4.15
*/
class GF_OSDXP {
/**
* @var GF_OSDXP
*/
private static $instance;
/**
* @var array The array of page slugs.
*/
private $slugs = array();
/**
* Class constructor.
*
* @since 2.4.15
*/
private function __construct() {
$this->slugs = [
'gf_settings' => esc_html__( 'Settings', 'gravityforms' ),
'gf_export' => esc_html__( 'Import/Export', 'gravityforms' ),
'gf_addons' => esc_html__( 'Add-Ons', 'gravityforms' ),
'gf_help' => esc_html__( 'Help', 'gravityforms' ),
'gf_system_status' => esc_html__( 'System Status', 'gravityforms' ),
];
add_filter( 'osdxp_license_key_gravityforms', array( $this, 'license_key' ) );
add_filter( 'osdxp_dashboard_license_submit_response', array( $this, 'process_license_key_submit' ), 10, 3 );
add_filter( 'osdxp_dashboard_license_deletion_response', array(
$this,
'process_license_key_deletion',
), 10, 2 );
add_filter( 'osdxp_add_module_settings_page', array( $this, 'settings_page' ) );
add_filter( 'parent_file', array( $this, 'settings_page_highlight' ) );
add_action( 'in_admin_header', array( $this, 'nav_tabs' ) );
}
/**
* Get a class instance.
*
* @since 2.4.15
*
* @return GF_OSDXP instance of GF_OSDXP.
*/
public static function get_instance() {
if ( ! self::$instance ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Handles the license key display.
*
* @since 2.4.15
*
* @param $license_key
*
* @return string|null Return a string or null to display the text box.
*/
public static function license_key( $license_key ) {
$version_info = GFCommon::get_version_info( false );
$key = GFCommon::get_key();
if ( ! rgempty( 'is_error', $version_info ) ) {
return esc_attr__( 'There was an error while validating your license key. Gravity Forms will continue to work, but automatic upgrades will not be available. Please contact support to resolve this issue.', 'gravityforms' );
} elseif ( rgar( $version_info, 'is_valid_key' ) ) {
return esc_html__( 'Valid', 'gravityforms' );
} elseif ( ! empty( $key ) ) {
return esc_html__( 'Invalid or Expired.', 'gravityforms' );
}
}
/**
* Process license key submit.
*
* Callback for the 'osdxp_dashboard_license_submit_response' filter.
*
* @since 2.4.15
*
* @param array $response Response.
* @param string $plugin_slug Plugin slug.
* @param string $license_key License key.
*
* @return array Response array.
*/
public static function process_license_key_submit( $response, $plugin_slug, $license_key ) {
if ( 'gravityforms' !== $plugin_slug ) {
return $response;
}
if ( ! is_array( $response ) ) {
$response = array();
}
// Sanitize license key.
$license_key = sanitize_text_field( $license_key );
GFFormsModel::save_key( $license_key );
// Updating message because key could have been changed.
GFCommon::cache_remote_message();
// Re-caching version info.
$version_info = GFCommon::get_version_info( false );
$error_message = '';
$key = GFCommon::get_key();
if ( ! rgempty( 'is_error', $version_info ) ) {
$error_message = esc_attr__( 'There was an error while validating your license key. Gravity Forms will continue to work, but automatic upgrades will not be available. Please contact support to resolve this issue.', 'gravityforms' );
} elseif ( rgar( $version_info, 'is_valid_key' ) ) {
update_option( 'gform_pending_installation', 0 );
if ( ! get_option( 'rg_gforms_currency' ) ) {
update_option( 'rg_gforms_currency', 'USD' );
}
$success_message = esc_html__( 'Valid Key : Your license key has been successfully validated.', 'gravityforms' );
if ( empty( $response['success_messages'] ) || ! is_array( $response['success_messages'] ) ) {
$response['success_messages'] = array();
}
$response['success_messages'][] = $success_message;
} elseif ( rgar( $version_info, 'reason' ) == 'requires_enterprise_license' ) {
$error_message = esc_html__( 'Invalid Key - an Enterprise license is required.', 'gravityforms' );
} elseif ( ! empty( $key ) ) {
$error_message = esc_html__( 'Invalid or Expired Key - Please make sure you have entered the correct value and that your key is not expired.', 'gravityforms' );
}
if ( ! empty( $error_message ) ) {
if ( empty( $response['error_messages'] ) || ! is_array( $response['error_messages'] ) ) {
$response['error_messages'] = array();
}
$response['error_messages'][] = $error_message;
}
return $response;
}
/**
* Process the license key deletion.
*
* @since 2.4.15
*
* @param $response
* @param $plugin_slug
*
* @return array
*/
public static function process_license_key_deletion( $response, $plugin_slug ) {
if ( $plugin_slug != 'gravityforms' ) {
return $response;
}
if ( ! is_array( $response ) ) {
$response = array();
}
GFFormsModel::save_key( '' );
$response['success'] = 1;
if ( empty( $response['success_messages'] ) || ! is_array( $response['success_messages'] ) ) {
$response['success_messages'] = array();
}
$response['success_messages'][] = esc_html__( 'License successfully removed.', 'gravityforms' );
return $response;
}
/**
* Registers plugin pages with osDXP.
*
* @since 2.4.15
*
* @param $pages
*
* @return array
*/
public function settings_page( $pages ) {
/**
* Setup.
*/
$has_full_access = current_user_can( 'gform_full_access' );
$min_cap = GFCommon::current_user_can_which( GFCommon::all_caps() );
if ( empty( $min_cap ) ) {
$min_cap = 'gform_full_access';
}
$parent_menu = array(
'name' => 'gf_edit_forms',
'callback' => array('GFForms', 'forms')
);
/**
* Remove Classic WP-Admin menu items.
*/
global $admin_page_hooks;
static $removed = false;
if ( ! $removed && is_array( $admin_page_hooks ) ) {
$removed = true;
remove_menu_page( $parent_menu['name'] );
remove_submenu_page( $parent_menu['name'], 'gf_settings' );
remove_submenu_page( $parent_menu['name'], 'gf_export' );
remove_submenu_page( $parent_menu['name'], 'gf_addons' );
remove_submenu_page( $parent_menu['name'], 'gf_system_status' );
remove_submenu_page( $parent_menu['name'], 'gf_help' );
}
/**
* Add osDXP specific pages.
*/
// Top-level action page.
$pages[] = array(
'function' => $parent_menu['callback'],
'type' => 'menu',
'menu_slug' => $parent_menu['name'],
'page_title' => esc_html__( 'Forms', 'gravityforms' ),
'menu_title' => esc_html__( 'Forms', 'gravityforms' ),
'capability' => $has_full_access ? 'gform_full_access' : $min_cap,
'icon_url' => GFForms::get_admin_icon_b64( '#FFF' ),
);
// Settings page.
$pages[] = array(
'function' => array( 'GFForms', 'settings_page' ),
'menu_slug' => 'gf_settings',
'page_title' => esc_html__( 'Form Settings', 'gravityforms' ),
'menu_title' => esc_html__( 'Form Settings', 'gravityforms' ),
'capability' => $has_full_access ? 'gform_full_access' : 'gravityforms_view_settings',
);
// Export page.
$pages[] = array(
'function' => array( 'GFForms', 'export_page' ),
'menu_slug' => 'gf_export',
'type' => 'endpoint',
'page_title' => esc_html__( 'Import/Export', 'gravityforms' ),
'menu_title' => esc_html__( 'Import/Export', 'gravityforms' ),
'capability' => $has_full_access ? 'gform_full_access' : ( current_user_can( 'gravityforms_export_entries' ) ? 'gravityforms_export_entries' : 'gravityforms_edit_forms' ),
);
if ( current_user_can( 'install_plugins' ) ) {
// Add-ons page.
$pages[] = array(
'function' => array( 'GFForms', 'addons_page' ),
'menu_slug' => 'gf_addons',
'type' => 'endpoint',
'page_title' => esc_html__( 'Add-Ons', 'gravityforms' ),
'menu_title' => esc_html__( 'Add-Ons', 'gravityforms' ),
'capability' => $has_full_access ? 'gform_full_access' : 'gravityforms_view_addons',
);
}
// System status page.
$pages[] = array(
'function' => array( 'GFForms', 'system_status' ),
'menu_slug' => 'gf_system_status',
'type' => 'endpoint',
'page_title' => esc_html__( 'System Status', 'gravityforms' ),
'menu_title' => esc_html__( 'System Status', 'gravityforms' ),
'capability' => $has_full_access ? 'gform_full_access' : 'gravityforms_system_status',
);
// Help page.
$pages[] = array(
'function' => array( 'GFForms', 'help_page' ),
'menu_slug' => 'gf_help',
'type' => 'endpoint',
'page_title' => esc_html__( 'Help', 'gravityforms' ),
'menu_title' => esc_html__( 'Help', 'gravityforms' ),
'capability' => $has_full_access ? 'gform_full_access' : $min_cap,
);
return $pages;
}
/**
* Helper function to check if a page slug is a setting/misc page.
*
* @since 2.4.15
*
* @param $plugin_page
*
* @return bool
*/
private function is_setting_page( $plugin_page ) {
return array_key_exists( $plugin_page, $this->slugs );
}
/**
* Highlights appropriate menu item for misc pages.
*
* @since 2.4.15
*
* @param $file
*
* @return $file
*/
public function settings_page_highlight( $file ) {
global $plugin_page, $submenu_file;
if ( $this->is_setting_page( $plugin_page ) ) {
$file = 'dxp-module-settings';
$submenu_file = 'gf_settings';
}
return $file;
}
/**
* Outputs Nav Tabs for settings&misc pages.
*
* @since 2.4.15
*/
public function nav_tabs() {
global $plugin_page;
if ( $this->is_setting_page( $plugin_page ) ) {
?>
<ul class="osdxp-nav-tabs">
<?php
foreach ( $this->slugs as $path => $name ) {
?>
<li <?php echo ( $path === $plugin_page ) ? 'class="active"' : '' ?>>
<a href="<?php echo admin_url( 'admin.php?page=' . $path ); ?>">
<?php echo $name; ?>
</a>
</li>
<?php
} ?>
</ul>
<?php
}
}
}
GF_OSDXP::get_instance();

View File

@@ -1,94 +0,0 @@
<?php
namespace Gravity_Forms\Gravity_Forms;
/**
* Class GF_Service_Container
*
* A simple Service Container used to collect and organize Services used by the application and its modules.
*
* @since 2.5
*
* @package Gravity_Forms\Gravity_Forms
*/
class GF_Service_Container {
private $services = array();
private $providers = array();
/**
* Add a service to the container.
*
* @since 2.5
*
* @param string $name The service Name
* @param mixed $service The service to add
*/
public function add( $name, $service, $defer = false ) {
if ( empty( $name ) ) {
$name = get_class( $service );
}
if ( ! $defer && is_callable( $service ) ) {
$service = $service();
}
$this->services[ $name ] = $service;
}
/**
* Remove a service from the container.
*
* @since 2.5
*
* @param string $name The service name.
*/
public function remove( $name ) {
unset( $this->services[ $name ] );
}
/**
* Get a service from the container by name.
*
* @since 2.5
*
* @param string $name The service name.
*
* @return mixed|null
*/
public function get( $name ) {
if ( ! isset( $this->services[ $name ] ) ) {
return null;
}
if ( is_callable( $this->services[ $name ] ) ) {
$called = $this->services[ $name ]();
$this->services[ $name ] = $called;
}
return $this->services[ $name ];
}
/**
* Add a service provider to the container and register each of its services.
*
* @since 2.5
*
* @param GF_Service_Provider $provider
*/
public function add_provider( GF_Service_Provider $provider ) {
$provider_name = get_class( $provider );
// Only add providers a single time.
if ( isset( $this->providers[ $provider_name ] ) ) {
return;
}
$this->providers[ $provider_name ] = $provider;
$provider->set_container( $this );
$provider->register( $this );
$provider->init( $this );
}
}

View File

@@ -1,107 +0,0 @@
<?php
namespace Gravity_Forms\Gravity_Forms;
use Gravity_Forms\Gravity_Forms\Config\GF_App_Config;
use Gravity_Forms\Gravity_Forms\Config\GF_Config_Service_Provider;
/**
* Class GF_Service_Provider
*
* An abstraction which provides a contract for defining Service Providers. Service Providers facilitate
* organizing Services into discreet modules, as opposed to having to register each service in a single location.
*
* @since 2.5
*
* @package Gravity_Forms\Gravity_Forms
*/
abstract class GF_Service_Provider {
/**
* @var GF_Service_Container $container
*/
protected $container;
public function set_container( GF_Service_Container $container ) {
$this->container = $container;
}
/**
* Register new services to the Service Container.
*
* @param GF_Service_Container $container
*
* @return void
*/
abstract public function register( GF_Service_Container $container );
/**
* Noop by default - used to initialize hooks and filters for the given module.
*/
public function init( GF_Service_Container $container ) {}
//----------------------------------------
//---------- App Registration ------------
//----------------------------------------
/**
* Register a JS app with the given arguments.
*
* @since 2.7.1
*
* @param array $args
*/
public function register_app( $args ) {
$config = new GF_App_Config( $this->container->get( GF_Config_Service_Provider::DATA_PARSER ) );
$config->set_data( $args );
$this->container->get( GF_Config_Service_Provider::CONFIG_COLLECTION )->add_config( $config );
$should_display = is_callable( $args['enqueue'] ) ? call_user_func( $args['enqueue'] ) : $args['enqueue'];
if ( ! $should_display ) {
return;
}
if ( ! empty( $args['css'] ) ) {
$this->enqueue_app_css( $args );
}
if ( ! empty( $args['root_element'] ) ) {
$this->add_root_element( $args['root_element'] );
}
}
/**
* Enqueue the CSS assets for the app.
*
* @since 2.7.1
*
* @param $args
*/
protected function enqueue_app_css( $args ) {
$css_asset = $args['css'];
add_action( 'wp_enqueue_scripts', function () use ( $css_asset ) {
call_user_func_array( 'wp_enqueue_style', $css_asset );
} );
add_action( 'admin_enqueue_scripts', function () use ( $css_asset ) {
call_user_func_array( 'wp_enqueue_style', $css_asset );
} );
}
/**
* Add the root element to the footer output for bootstrapping.
*
* @since 2.7.1
*
* @param string $root
*/
protected function add_root_element( $root ) {
add_action( 'admin_footer', function() use ( $root ) {
echo '<div data-js="' . $root . '"></div>';
}, 10, 0 );
}
}

View File

@@ -1,551 +0,0 @@
<?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
*
* @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|WP_Error
*/
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, true );
if ( is_wp_error( $result ) ) {
GFCommon::log_error( __METHOD__ . '(): error registering site. ' . $result->get_error_message() );
return $result;
}
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
* @since 2.5 Returns License Response on success.
*
* @access public
*
* @param string $new_license_key_md5 Hash license key to be updated
*
* @return \Gravity_Forms\Gravity_Forms\License\GF_License_API_Response|WP_Error
*/
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, true );
if ( is_wp_error( $result ) ) {
GFCommon::log_debug( __METHOD__ . '(): error updating site registration. ' . print_r( $result, true ) );
return $result;
}
return $result;
}
/***
* 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, true );
if ( is_wp_error( $result ) ) {
GFCommon::log_debug( __METHOD__ . '(): error updating site registration. ' . print_r( $result, true ) );
return $result;
}
return true;
}
/**
* Check the given license key to get its information from the API.
*
* @since 2.5
*
* @param string $key The license key.
*
* @return array|false|WP_Error
*/
public function check_license( $key ) {
GFCommon::log_debug( __METHOD__ . '(): getting site and license info' );
$params = array(
'site_url' => get_option( 'home' ),
'is_multisite' => is_multisite(),
);
$resource = 'licenses/' . $key . '/check?' . build_query( $params );
$result = $this->request( $resource, null );
$result = $this->prepare_response_body( $result, true );
if ( is_wp_error( $result ) ) {
GFCommon::log_debug( __METHOD__ . '(): error getting site and license information. ' . $result->get_error_message() );
return $result;
}
$response = $result;
if ( rgar( $result, 'license' ) ) {
$response = rgar( $result, 'license' );
}
// Set the license object to the transient.
set_transient( 'rg_gforms_license', $response, DAY_IN_SECONDS );
return $response;
}
/**
* Get GF core and add-on family information.
*
* @since 2.5
*
* @return false|array
*/
public function get_plugins_info() {
$version_info = $this->get_version_info();
if ( empty( $version_info['offerings'] ) ) {
return false;
}
return $version_info['offerings'];
}
/**
* Get version information from the Gravity Manager API.
*
* @since 2.5
*
* @param false $cache
*
* @return array
*/
private function get_version_info( $cache = false ) {
$version_info = null;
if ( $cache ) {
$cached_info = get_option( 'gform_version_info' );
// Checking cache expiration
$cache_duration = DAY_IN_SECONDS; // 24 hours.
$cache_timestamp = $cached_info && isset( $cached_info['timestamp'] ) ? $cached_info['timestamp'] : 0;
// Is cache expired? If not, set $version_info to the cached data.
if ( $cache_timestamp + $cache_duration >= time() ) {
$version_info = $cached_info;
}
}
if ( is_wp_error( $version_info ) || isset( $version_info['headers'] ) ) {
// Legacy ( < 2.1.1.14 ) version info contained the whole raw response.
$version_info = null;
}
// If we reach this point with a $version_info array, it's from cache, and we can return it.
if ( $version_info ) {
return $version_info;
}
//Getting version number
$options = array(
'method' => 'POST',
'timeout' => 20,
);
$options['headers'] = array(
'Content-Type' => 'application/x-www-form-urlencoded; charset=' . get_option( 'blog_charset' ),
'User-Agent' => 'WordPress/' . get_bloginfo( 'version' ),
);
$options['body'] = GFCommon::get_remote_post_params();
$options['timeout'] = 15;
$nocache = $cache ? '' : 'nocache=1'; //disabling server side caching
$raw_response = GFCommon::post_to_manager( 'version.php', $nocache, $options );
$version_info = array(
'is_valid_key' => '1',
'version' => '',
'url' => '',
'is_error' => '1',
);
if ( is_wp_error( $raw_response ) || rgars( $raw_response, 'response/code' ) != 200 ) {
$version_info['timestamp'] = time();
return $version_info;
}
$decoded = json_decode( $raw_response['body'], true );
if ( empty( $decoded ) ) {
$version_info['timestamp'] = time();
return $version_info;
}
$decoded['timestamp'] = time();
// Caching response.
update_option( 'gform_version_info', $decoded, false ); //caching version info
return $decoded;
}
/**
* Update the usage data (call version.php in Gravity Manager). We will replace it once we have statistics API endpoints.
*
* @since 2.5
*/
public function update_site_data() {
// Whenever we update the plugins info, we call the versions.php to update usage data.
$options = array( 'method' => 'POST' );
$options['headers'] = array(
'Content-Type' => 'application/x-www-form-urlencoded; charset=' . get_option( 'blog_charset' ),
'User-Agent' => 'WordPress/' . get_bloginfo( 'version' ),
'Referer' => get_bloginfo( 'url' ),
);
$options['body'] = GFCommon::get_remote_post_params();
// Set the version to 3 which lightens the burden of version.php, it won't return anything to us anymore.
$options['body']['version'] = '3';
$options['timeout'] = 15;
$nocache = 'nocache=1'; //disabling server side caching
GFCommon::post_to_manager( 'version.php', $nocache, $options );
}
public function send_email_to_hubspot( $email ) {
GFCommon::log_debug( __METHOD__ . '(): Sending installation wizard to hubspot.' );
$body = array(
'email' => $email,
);
$result = $this->request( 'emails/installation/add-to-list', $body, 'POST', array( 'headers' => $this->get_license_info_header( $site_secret ) ) );
$result = $this->prepare_response_body( $result, true );
if ( is_wp_error( $result ) ) {
GFCommon::log_debug( __METHOD__ . '(): error sending installation wizard to hubspot. ' . print_r( $result, true ) );
return $result;
}
return true;
}
// # HELPERS
/**
* @return false|mixed|void
*/
public function get_key() {
return GFCommon::get_key();
}
/**
* @param $site_key
* @param $site_secret
*
* @return string[]
*/
private function get_site_auth_header( $site_key, $site_secret ) {
$auth = base64_encode( "{$site_key}:{$site_secret}" );
return array( 'Authorization' => 'GravityAPI ' . $auth );
}
/**
* @param $site_secret
*
* @return string[]
*/
private function get_license_info_header( $site_secret ) {
$auth = base64_encode( "gravityforms.com:{$site_secret}" );
return array( 'Authorization' => 'GravityAPI ' . $auth );
}
/**
* @param $license_key_md5
*
* @return string[]
*/
private function get_license_auth_header( $license_key_md5 ) {
$auth = base64_encode( "license:{$license_key_md5}" );
return array( 'Authorization' => 'GravityAPI ' . $auth );
}
/**
* Prepare response body.
*
* @since unknown
* @since 2.5 Support a WP_Error being returned.
* @since 2.5 Allow results to be returned as array with second param.
*
* @param WP_Error|WP_REST_Response $raw_response The API response.
* @param bool $as_array Whether to return the response as an array or object.
*
* @return array|object|WP_Error
*/
public function prepare_response_body( $raw_response, $as_array = false ) {
if ( is_wp_error( $raw_response ) ) {
return $raw_response;
}
$response_body = json_decode( wp_remote_retrieve_body( $raw_response ), $as_array );
$response_code = wp_remote_retrieve_response_code( $raw_response );
$response_message = wp_remote_retrieve_response_message( $raw_response );
if ( $response_code > 200 ) {
// If a WP_Error was returned in the body.
if ( rgar( $response_body, 'code' ) ) {
// Restore the WP_Error.
$error = new WP_Error( $response_body['code'], $response_body['message'], $response_body['data'] );
} else {
$error = new WP_Error( 'server_error', 'Error from server: ' . $response_message );
}
return $error;
}
return $response_body;
}
/**
* Purge the site credentials.
*
* @since unknown
* @since 2.5 Added the deletion of the gf_site_registered option.
*/
public function purge_site_credentials() {
delete_option( 'gf_site_key' );
delete_option( 'gf_site_secret' );
delete_option( 'gf_site_registered' );
}
/**
* Making API requests.
*
* @since unknown
* @since 2.5 Purge the registration data on site if certain errors matched.
*
* @param string $resource The API route.
* @param array $body The request body.
* @param string $method The method.
* @param array $options The options.
*
* @return array|WP_Error
*/
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;
return wp_remote_request( $request_url, $options );
}
/**
* @return false|mixed|void
*/
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;
}
/**
* @return false|mixed|void
*/
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;
}
/**
* @return string
*/
public function get_gravity_api_url() {
return trailingslashit( GRAVITY_API_URL );
}
/**
* Check if the site has the gf_site_key and gf_site_secret options.
*
* @since unknown
*
* @return bool
*/
public function is_site_registered() {
return $this->get_site_key() && $this->get_site_secret();
}
/**
* Check if the site has the gf_site_key, gf_site_secret and also the gf_site_registered options.
*
* @since 2.5
*
* @return bool
*/
public function is_legacy_registration() {
return $this->is_site_registered() && ! get_option( 'gf_site_registered' );
}
}
function gapi() {
return Gravity_Api::get_instance();
}
gapi();
}

View File

@@ -1,483 +0,0 @@
<?php
namespace Gravity_Forms\Gravity_Forms;
use GFCommon;
/**
* Allows to download translations from TranslationsPress
* This is a modified version of the library available at https://github.com/WP-Translations/t15s-registry
* This version aims to be compatible with PHP 5.2, and supports only plugins.
*
* @since 2.5
*/
class TranslationsPress_Updater {
const T15S_TRANSIENT_KEY = 't15s-registry-gforms';
const T15S_API_URL = 'https://packages.translationspress.com/rocketgenius/packages.json';
/**
* The plugin slug.
*
* @since 2.5
*
* @var string
*/
private $slug = '';
/**
* The locales installed during the current request.
*
* @since 2.5.6
*
* @var array
*/
private $installed = array();
/**
* Cached TranslationsPress data for all Rocketgenius plugins.
*
* @since 2.5.6
*
* @var null|object
*/
private static $all_translations;
/**
* The current instances of this class with the slugs as the keys.
*
* @since 2.5.6
*
* @var TranslationsPress_Updater[]
*/
private static $_instances = array();
/**
* Returns an instance of this class for the given slug.
*
* @since 2.5.6
*
* @param string $slug The plugin slug.
*
* @return TranslationsPress_Updater
*/
public static function get_instance( $slug ) {
if ( empty( self::$_instances[ $slug ] ) ) {
self::$_instances[ $slug ] = new self( $slug );
}
return self::$_instances[ $slug ];
}
/**
* Adds a new project to load translations for.
*
* @since 2.5
*
* @param string $slug The plugin slug.
* @param string $deprecated Not used. Previously, the locale to be installed.
*/
public function __construct( $slug, $deprecated = '' ) {
$this->slug = $slug;
if ( 'gravityforms' === $slug ) {
// Translations data for all Rocketgenius plugins is stored together so we only need to add this hook once.
add_action( 'delete_site_transient_update_plugins', array( __CLASS__, 'refresh_all_translations' ) );
}
add_action( 'gform_post_install', array( $this, 'install' ), 10, 0 );
add_action( 'gform_post_upgrade', array( $this, 'install' ), 10, 0 );
add_action( 'upgrader_process_complete', array( $this, 'upgrader_process_complete' ), 10, 2 );
add_filter( 'translations_api', array( $this, 'translations_api' ), 10, 3 );
add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'site_transient_update_plugins' ) );
}
/**
* Short-circuits translations API requests for private projects.
*
* @since 2.5
*
* @param bool|array $result The result object. Default false.
* @param string $requested_type The type of translations being requested.
* @param object $args Translation API arguments.
*
* @return bool|array
*/
public function translations_api( $result, $requested_type, $args ) {
if ( 'plugins' !== $requested_type || $this->slug !== $args['slug'] ) {
return $result;
}
return $this->get_plugin_translations();
}
/**
* Filters the translations transients to include the current plugin.
*
* @see wp_get_translation_updates()
*
* @since 2.5
*
* @param mixed $value The transient value.
*
* @return object
*/
public function site_transient_update_plugins( $value ) {
if ( ! $value ) {
$value = new \stdClass();
}
if ( ! isset( $value->translations ) ) {
$value->translations = array();
}
$translations = $this->get_plugin_translations();
if ( empty( $translations['translations'] ) ) {
return $value;
}
foreach ( $translations['translations'] as $translation ) {
if ( ! $this->should_install( $translation ) ) {
continue;
}
$translation['type'] = 'plugin';
$translation['slug'] = $this->slug;
$value->translations[] = $translation;
}
return $value;
}
/**
* Gets the TranslationsPress data for the current plugin.
*
* @since 2.5
*
* @return array
*/
private function get_plugin_translations() {
self::set_all_translations();
return (array) rgar( self::$all_translations->projects, $this->slug );
}
/**
* Refreshes the cached TranslationsPress data, if expired.
*
* @since 2.5.6
*/
public static function refresh_all_translations() {
static $done;
if ( $done ) {
return;
}
self::$all_translations = null;
self::set_all_translations();
$done = true;
}
/**
* Determines if the cached TranslationsPress data needs refreshing.
*
* @since 2.5.6
*
* @return bool
*/
private static function is_transient_expired() {
$cache_lifespan = 12 * HOUR_IN_SECONDS;
return ! isset( self::$all_translations->_last_checked ) || ( time() - self::$all_translations->_last_checked ) > $cache_lifespan;
}
/**
* Gets the translations data from the TranslationsPress API.
*
* @since 2.5.6
*
* @return array
*/
private static function get_remote_translations_data() {
$result = json_decode( wp_remote_retrieve_body( wp_remote_get( self::T15S_API_URL, array( 'timeout' => 3 ) ) ), true );
return is_array( $result ) ? $result : array();
}
/**
* Caches the TranslationsPress data, if not already cached.
*
* @since 2.5.6
*/
private static function set_all_translations() {
if ( is_object( self::$all_translations ) ) {
return;
}
self::$all_translations = get_site_transient( self::T15S_TRANSIENT_KEY );
if ( is_object( self::$all_translations ) && ! self::is_transient_expired() ) {
return;
}
self::$all_translations = new \stdClass();
self::$all_translations->projects = self::get_remote_translations_data();
self::$all_translations->_last_checked = time();
set_site_transient( self::T15S_TRANSIENT_KEY, self::$all_translations );
}
/**
* Gets the translations for a given project.
*
* @since 2.5
*
* @deprecated 2.5.6
*
* @param string $url Full GlotPress API URL for the project.
*
* @return array Translation data.
*/
public static function get_translations( $url ) {
_deprecated_function( __METHOD__, '2.5.6', '\Gravity_Forms\Gravity_Forms\TranslationsPress_Updater::get_plugin_translations' );
self::set_all_translations();
return self::$all_translations->projects;
}
/**
* Downloads and installs the translations for the specified plugin.
*
* @since 2.5
*
* @param string $slug The plugin slug.
* @param string $locale The locale when the site locale is changed or an empty string to install all the user available locales.
*/
public static function download_package( $slug, $locale = '' ) {
self::get_instance( $slug )->install( $locale );
}
/**
* Triggers translation installation, if required.
*
* @since 2.5.6
*
* @param string $locale The locale when the site locale is changed or an empty string to install all the user available locales.
*/
public function install( $locale = '' ) {
if ( $locale && in_array( $locale, $this->installed ) ) {
return;
}
$translations = $this->get_plugin_translations();
if ( empty( $translations['translations'] ) ) {
GFCommon::log_error( __METHOD__ . sprintf( '(): Aborting; No translations list for %s.', $this->slug ) );
return;
}
foreach ( $translations['translations'] as $translation ) {
if ( ! $this->should_install( $translation, $locale ) ) {
continue;
}
$this->install_translation( $translation );
if ( $locale ) {
return;
}
}
}
/**
* Downloads and installs the given translation.
*
* @since 2.5.6
*
* @param array $translation The translation data.
*/
private function install_translation( $translation ) {
global $wp_filesystem;
if ( ! $wp_filesystem ) {
require_once ABSPATH . '/wp-admin/includes/admin.php';
// Same approach as in WP Core: https://github.com/WordPress/wordpress-develop/blob/6.2/src/wp-includes/rest-api/endpoints/class-wp-rest-plugins-controller.php#L853-L869.
ob_start();
$filesystem_credentials_available = request_filesystem_credentials( self_admin_url() );
ob_end_clean();
if ( ! $filesystem_credentials_available ) {
GFCommon::log_error( __METHOD__ . '(): Aborting; filesystem credentials required.' );
return;
}
if ( ! \WP_Filesystem() ) {
GFCommon::log_error( __METHOD__ . '(): Aborting; unable to init WP_Filesystem.' );
return;
}
}
$lang_dir = $this->get_path();
if ( ! $wp_filesystem->is_dir( $lang_dir ) ) {
$wp_filesystem->mkdir( $lang_dir, FS_CHMOD_DIR );
}
GFCommon::log_debug( __METHOD__ . '(): Downloading: ' . $translation['package'] );
$temp_file = download_url( $translation['package'] );
if ( is_wp_error( $temp_file ) ) {
GFCommon::log_error( __METHOD__ . '(): Error downloading package. Code: ' . $temp_file->get_error_code() . '; Message: ' . $temp_file->get_error_message() );
return;
}
$zip_path = $lang_dir . $this->slug . '-' . $translation['language'] . '.zip';
$copy_result = $wp_filesystem->copy( $temp_file, $zip_path, true, FS_CHMOD_FILE );
$wp_filesystem->delete( $temp_file );
if ( ! $copy_result ) {
GFCommon::log_error( __METHOD__ . '(): Unable to move package to: ' . $lang_dir );
return;
}
$result = unzip_file( $zip_path, $lang_dir );
@unlink( $zip_path );
if ( is_wp_error( $result ) ) {
GFCommon::log_error( __METHOD__ . '(): Error extracting package. Code: ' . $result->get_error_code() . '; Message: ' . $result->get_error_message() );
return;
}
GFCommon::log_debug( __METHOD__ . sprintf( '(): Installed %s translation for %s.', $translation['language'], $this->slug ) );
$this->installed[] = $translation['language'];
}
/**
* Logs which locales WordPress installs translations for.
*
* @since 2.5.6
*
* @param object $upgrader_object WP_Upgrader Instance.
* @param array $hook_extra Item update data.
*/
public function upgrader_process_complete( $upgrader_object, $hook_extra ) {
if ( rgar( $hook_extra, 'type' ) !== 'translation' || empty( $hook_extra['translations'] ) || empty( $upgrader_object->result ) || is_wp_error( $upgrader_object->result ) ) {
return;
}
$locales = array();
foreach ( $hook_extra['translations'] as $translation ) {
if ( rgar( $translation, 'type' ) !== 'plugin' || rgar( $translation, 'slug' ) !== $this->slug ) {
continue;
}
$locales[] = $translation['language'];
}
if ( empty( $locales ) ) {
return;
}
$this->installed = $locales;
GFCommon::log_debug( __METHOD__ . sprintf( '(): WordPress installed %s translation(s) for %s.', implode( ', ', $locales ), $this->slug ) );
}
/**
* Returns an array of locales the site has installed.
*
* @since 2.5.6
*
* @return array
*/
private function get_available_languages() {
static $languages = array();
if ( empty( $languages ) ) {
$languages = get_available_languages();
}
return $languages;
}
/**
* Returns the header data from the installed translations for the current plugin.
*
* @since 2.5.6
*
* @return array
*/
private function get_installed_translations_data() {
static $data = array();
if ( isset( $data[ $this->slug ] ) ) {
return $data[ $this->slug ];
}
$data[ $this->slug ] = array();
$translations = GFCommon::get_installed_translations( $this->slug, true );
foreach ( $translations as $locale => $mo_file ) {
$po_file = str_replace( '.mo', '.po', $mo_file );
if ( ! file_exists( $po_file ) ) {
continue;
}
$data[ $this->slug ][ $locale ] = wp_get_pomo_file_data( $po_file );
}
return $data[ $this->slug ];
}
/**
* Returns the path to where plugin translations are stored.
*
* @since 2.5.6
*
* @return string
*/
private function get_path() {
return WP_LANG_DIR . '/plugins/';
}
/**
* Determines if a translation should be installed.
*
* @since 2.5.6
*
* @param array $translation The translation data.
* @param string $locale The locale when the site locale is changed or an empty string to check all the user available locales.
*
* @return bool
*/
private function should_install( $translation, $locale = '' ) {
if ( ( $locale && $locale !== $translation['language'] ) || ! in_array( $translation['language'], $this->get_available_languages() ) ) {
return false;
}
if ( empty( $translation['updated'] ) ) {
return true;
}
$installed = $this->get_installed_translations_data();
if ( ! isset( $installed[ $translation['language'] ] ) ) {
return true;
}
$local = date_create( $installed[ $translation['language'] ]['PO-Revision-Date'] );
$remote = date_create( $translation['updated'] );
return $remote > $local;
}
}
TranslationsPress_Updater::get_instance( 'gravityforms' );

View File

@@ -1,95 +0,0 @@
<?php
namespace Gravity_Forms\Gravity_Forms\Config;
use Gravity_Forms\Gravity_Forms\Config\GF_Config_Collection;
use Gravity_Forms\Gravity_Forms\Config\GF_Config;
use Gravity_Forms\Gravity_Forms\Config\GF_Configurator;
/**
* Config items for app registration, including helper methods.
*
* @since 2.7.1
*/
class GF_App_Config extends GF_Config {
/**
* The name of the app, in slug form.
*
* @var string $app_name
*/
private $app_name;
/**
* The condition for enqueuing the app data.
*
* @var bool|callable $display_condition
*/
private $display_condition;
/**
* The CSS assets to enqueue.
*
* @var array $css_asset
*/
private $css_asset;
/**
* The relative path to the chunk in JS.
*
* @var string $chunk
*/
private $chunk;
/**
* The root element to use to load the app.
*
* @var string $root_element
*/
private $root_element;
/**
* Set the data for this app config.
*
* @since 2.7.1
*
* @param $data
*/
public function set_data( $data ) {
$this->name = $data['object_name'];
$this->script_to_localize = $data['script_name'];
$this->app_name = $data['app_name'];
$this->display_condition = $data['enqueue'];
$this->chunk = $data['chunk'];
$this->root_element = $data['root_element'];
}
/**
* Whether we should enqueue this data.
*
* @since 2.6
*
* @return bool|mixed
*/
public function should_enqueue() {
return is_admin();
}
/**
* Config data.
*
* @return array[]
*/
public function data() {
return array(
'apps' => array(
$this->app_name => array(
'should_display' => is_callable( $this->display_condition ) ? call_user_func( $this->display_condition ) : $this->display_condition,
'chunk_path' => $this->chunk,
'root_element' => $this->root_element,
),
),
);
}
}

View File

@@ -1,165 +0,0 @@
<?php
namespace Gravity_Forms\Gravity_Forms\Config;
use Gravity_Forms\Gravity_Forms\Config\GF_Config;
/**
* Collection to hold GF_Config items and provide their structured data when needed.
*
* @since 2.6
*
* @package Gravity_Forms\Gravity_Forms\Config
*/
class GF_Config_Collection {
/**
* @var GF_Config[] $configs
*/
private $configs = array();
/**
* Add a config to the collection.
*
* @param GF_Config $config
*/
public function add_config( GF_Config $config ) {
$this->configs[] = $config;
}
/**
* Handle outputting the config data.
*
* If $localize is true, data is actually localized via `wp_localize_script`, otherwise
* data is simply returned as an array.
*
* @since 2.6
*
* @param bool $localize Whether to localize the data, or simply return it.
*
* @return array
*/
public function handle( $localize = true ) {
$scripts = $this->get_configs_by_script();
$data_to_localize = array();
foreach ( $scripts as $script => $items ) {
$item_data = $this->localize_data_for_script( $script, $items, $localize );
$data_to_localize = array_merge( $data_to_localize, $item_data );
}
return $data_to_localize;
}
/**
* Localize the data for the given script.
*
* @since 2.6
*
* @param string $script
* @param GF_Config[] $items
*/
private function localize_data_for_script( $script, $items, $localize = true ) {
$data = array();
foreach ( $items as $name => $configs ) {
$localized_data = $this->get_merged_data_for_object( $configs );
/**
* Allows users to filter the data localized for a given script/resource.
*
* @since 2.6
*
* @param array $localized_data The current localize data
* @param string $script The script being localized
* @param array $configs An array of $configs being applied to this script
*
* @return array
*/
$localized_data = apply_filters( 'gform_localized_script_data_' . $name, $localized_data, $script, $configs );
$data[ $name ] = $localized_data;
if ( $localize ) {
wp_localize_script( $script, $name, $localized_data );
}
}
return $data;
}
/**
* Get the merged data object for the applicable configs. Will process each config by its
* $priority property, overriding or merging values as needed.
*
* @since 2.6
*
* @param GF_Config[] $configs
*/
private function get_merged_data_for_object( $configs ) {
// Squash warnings for PHP < 7.0 when running tests.
@usort( $configs, array( $this, 'sort_by_priority' ) );
$data = array();
foreach ( $configs as $config ) {
// Config is set to overwrite data - simply return its value without attempting to merge.
if ( $config->should_overwrite() ) {
$data = $config->get_data();
continue;
}
// Config should be merged - loop through each key and attempt to recursively merge the values.
foreach ( $config->get_data() as $key => $value ) {
$existing = isset( $data[ $key ] ) ? $data[ $key ] : null;
if ( is_null( $existing ) || ! is_array( $existing ) || ! is_array( $value ) ) {
$data[ $key ] = $value;
continue;
}
$data[ $key ] = array_merge_recursive( $existing, $value );
}
}
return $data;
}
/**
* Get the appropriate configs, organized by the script they belong to.
*
* @since 2.6
*
* @return array
*/
private function get_configs_by_script() {
$data_to_localize = array();
foreach ( $this->configs as $config ) {
if ( ( ! defined( 'GFORMS_DOING_MOCK' ) || ! GFORMS_DOING_MOCK ) && ! $config->should_enqueue() ) {
continue;
}
$data_to_localize[ $config->script_to_localize() ][ $config->name() ][] = $config;
}
return $data_to_localize;
}
/**
* usort() callback to sort the configs by their $priority.
*
* @param GF_Config $a
* @param GF_Config $b
*
* @return int
*/
public function sort_by_priority( GF_Config $a, GF_Config $b ) {
if ( $a->priority() === $b->priority() ) {
return 0;
}
return $a->priority() < $b->priority() ? - 1 : 1;
}
}

View File

@@ -1,77 +0,0 @@
<?php
namespace Gravity_Forms\Gravity_Forms\Config;
/**
* Parses a given data array to return either Live or Mock values, depending on the
* environment and context.
*
* @since 2.6
*
* @package Gravity_Forms\Gravity_Forms\Config
*/
class GF_Config_Data_Parser {
/**
* Parse the given $data array and get the correct values for the context.
*
* @since 2.6
*
* @param $data
*
* @return array
*/
public function parse( $data ) {
$return = array();
foreach( $data as $key => $value ) {
$return[ $key ] = $this->get_correct_value( $value );
}
return $return;
}
/**
* Loop through each array key and get the correct value. Is called recursively for
* nested arrays.
*
* @since 2.6
*
* @param mixed $value
*
* @return array|mixed
*/
private function get_correct_value( $value ) {
// Value isn't array - we've reached the final level for this branch.
if ( ! is_array( $value ) ) {
return $value;
}
// Value is an array with our defined value and default keys. Return either live or mock data.
if ( array_key_exists( 'default', $value ) && array_key_exists( 'value', $value ) ) {
return $this->is_mock() ? $value['default'] : $value['value'];
}
$data = array();
// Value is an array - recursively call this method to dig into each level and return the correct value.
foreach( $value as $key => $value ) {
$data[ $key ] = $this->get_correct_value( $value );
}
return $data;
}
/**
* Determine whether the current environmental context is a Mock context.
*
* @since 2.6
*
* @return bool
*/
private function is_mock() {
return defined( 'GFORMS_DOING_MOCK' ) && GFORMS_DOING_MOCK;
}
}

View File

@@ -1,209 +0,0 @@
<?php
namespace Gravity_Forms\Gravity_Forms\Config;
use Gravity_Forms\Gravity_Forms\Config\Items\GF_Config_Admin_I18n;
use Gravity_Forms\Gravity_Forms\Config\Items\GF_Config_Block_Editor;
use Gravity_Forms\Gravity_Forms\Config\Items\GF_Config_Global;
use Gravity_Forms\Gravity_Forms\Config\Items\GF_Config_I18n;
use Gravity_Forms\Gravity_Forms\Config\Items\GF_Config_Legacy_Check;
use Gravity_Forms\Gravity_Forms\Config\Items\GF_Config_Legacy_Check_Multi;
use Gravity_Forms\Gravity_Forms\Config\Items\GF_Config_Multifile;
use Gravity_Forms\Gravity_Forms\GF_Service_Container;
use Gravity_Forms\Gravity_Forms\GF_Service_Provider;
/**
* Class GF_Config_Service_Provider
*
* Service provider for the Config Service.
*
* @package Gravity_Forms\Gravity_Forms\Config
*/
class GF_Config_Service_Provider extends GF_Service_Provider {
// Organizational services
const CONFIG_COLLECTION = 'config_collection';
const DATA_PARSER = 'data_parser';
// Config services
const I18N_CONFIG = 'i18n_config';
const I18N_ADMIN_CONFIG = 'i18n_admin_config';
const LEGACY_CONFIG = 'legacy_config';
const LEGACY_MULTI_CONFIG = 'legacy_multi_config';
const MULTIFILE_CONFIG = 'multifile_config';
const BLOCK_EDITOR_CONFIG = 'block_editor_config';
const GLOBAL_CONFIG = 'global_config';
/**
* Array mapping config class names to their container ID.
*
* @since 2.6
*
* @var string[]
*/
protected $configs = array(
self::I18N_CONFIG => GF_Config_I18n::class,
self::I18N_ADMIN_CONFIG => GF_Config_Admin_I18n::class,
self::LEGACY_CONFIG => GF_Config_Legacy_Check::class,
self::LEGACY_MULTI_CONFIG => GF_Config_Legacy_Check_Multi::class,
self::MULTIFILE_CONFIG => GF_Config_Multifile::class,
self::BLOCK_EDITOR_CONFIG => GF_Config_Block_Editor::class,
);
/**
* Register services to the container.
*
* @since 2.6
*
* @param GF_Service_Container $container
*/
public function register( GF_Service_Container $container ) {
// Include required files.
require_once( plugin_dir_path( __FILE__ ) . 'class-gf-config-collection.php' );
require_once( plugin_dir_path( __FILE__ ) . 'class-gf-config.php' );
require_once( plugin_dir_path( __FILE__ ) . 'class-gf-config-data-parser.php' );
require_once( plugin_dir_path( __FILE__ ) . 'class-gf-app-config.php' );
require_once( plugin_dir_path( __FILE__ ) . 'items/class-gf-config-global.php' );
// Add to container
$container->add( self::CONFIG_COLLECTION, function () {
return new GF_Config_Collection();
} );
$container->add( self::DATA_PARSER, function () {
return new GF_Config_Data_Parser();
} );
$container->add( self::GLOBAL_CONFIG, function () {
return new GF_Config_Global();
} );
// Add configs to container.
$this->register_config_items( $container );
$this->register_configs_to_collection( $container );
}
/**
* Initiailize any actions or hooks.
*
* @since 2.6
*
* @param GF_Service_Container $container
*
* @return void
*/
public function init( GF_Service_Container $container ) {
// Need to pass $this to callbacks; save as variable.
$self = $this;
add_action( 'wp_enqueue_scripts', function () use ( $container ) {
$container->get( self::CONFIG_COLLECTION )->handle();
}, 9999 );
add_action( 'admin_enqueue_scripts', function () use ( $container ) {
$container->get( self::CONFIG_COLLECTION )->handle();
}, 9999 );
add_action( 'gform_preview_init', function () use ( $container ) {
$container->get( self::CONFIG_COLLECTION )->handle();
}, 0 );
add_action( 'rest_api_init', function () use ( $container, $self ) {
register_rest_route( 'gravityforms/v2', '/tests/mock-data', array(
'methods' => 'GET',
'callback' => array( $self, 'config_mocks_endpoint' ),
'permission_callback' => function () {
return true;
},
) );
} );
// Add global config data to admin and theme.
add_filter( 'gform_localized_script_data_gform_admin_config', function ( $data ) use ( $self ) {
return $self->add_global_config_data( $data );
} );
add_filter( 'gform_localized_script_data_gform_theme_config', function ( $data ) use ( $self ) {
return $self->add_global_config_data( $data );
} );
}
/**
* For each config defined in $configs, instantiate and add to container.
*
* @since 2.6
*
* @param GF_Service_Container $container
*
* @return void
*/
private function register_config_items( GF_Service_Container $container ) {
require_once( plugin_dir_path( __FILE__ ) . '/items/class-gf-config-i18n.php' );
require_once( plugin_dir_path( __FILE__ ) . '/items/class-gf-config-admin-i18n.php' );
require_once( plugin_dir_path( __FILE__ ) . '/items/class-gf-config-legacy-check.php' );
require_once( plugin_dir_path( __FILE__ ) . '/items/class-gf-config-legacy-check-multi.php' );
require_once( plugin_dir_path( __FILE__ ) . '/items/class-gf-config-multifile.php' );
require_once( plugin_dir_path( __FILE__ ) . '/items/class-gf-config-block-editor.php' );
$parser = $container->get( self::DATA_PARSER );
foreach ( $this->configs as $name => $class ) {
$container->add( $name, function () use ( $class, $parser ) {
return new $class( $parser );
} );
}
}
/**
* Register each config defined in $configs to the GF_Config_Collection.
*
* @since 2.6
*
* @param GF_Service_Container $container
*
* @return void
*/
public function register_configs_to_collection( GF_Service_Container $container ) {
$collection = $container->get( self::CONFIG_COLLECTION );
foreach ( $this->configs as $name => $config ) {
$config_class = $container->get( $name );
$collection->add_config( $config_class );
}
}
/**
* Callback for the Config Mocks REST endpoint.
*
* @since 2.6
*
* @return array
*/
public function config_mocks_endpoint() {
define( 'GFORMS_DOING_MOCK', true );
$container = \GFForms::get_service_container();
$data = $container->get( self::CONFIG_COLLECTION )->handle( false );
return $data;
}
/**
* Add global data to both admin and theme configs so that it is available everywhere
* within the system.
*
* @since 2.7
*
* @param $data
*
* @return array
*/
public function add_global_config_data( $data ) {
$container = \GFForms::get_service_container();
$global = $container->get( self::GLOBAL_CONFIG )->data();
return array_merge( $data, $global );
}
}

View File

@@ -1,190 +0,0 @@
<?php
namespace Gravity_Forms\Gravity_Forms\Config;
/**
* Base class for providing advanced functionality when localizing Config Data
* for usage in Javascript.
*
* @since 2.6
*
* @package Gravity_Forms\Gravity_Forms\Config
*/
abstract class GF_Config {
/**
* The Data Parser
*
* @since 2.6
*
* @var GF_Config_Data_Parser
*/
protected $parser;
/**
* The data for this config object.
*
* @since 2.6
*
* @var array
*/
protected $data;
/**
* The object name for this config.
*
* @since 2.6
*
* @var string
*/
protected $name;
/**
* The ID of the script to localize the data to.
*
* @since 2.6
*
* @var string
*/
protected $script_to_localize;
/**
* The priority of this config - can be used to control the order in
* which configs are processed in the Collection.
*
* @since 2.6
*
* @var int
*/
protected $priority = 0;
/**
* Whether the config should enqueue it's data. Can also be handled by overriding the
* ::should_enqueue() method.
*
* @since 2.6
*
* @var bool
*/
protected $should_enqueue = true;
/**
* Whether this config should overwrite previous values in the object.
*
* If set to "true", the object will be overwritten by the values provided here.
* If set to "false", the object will have its values merged with those defined here, recursively.
*
* @since 2.6
*
* @var bool
*/
protected $overwrite = false;
/**
* Constructor
*
* @param GF_Config_Data_Parser $parser
*/
public function __construct( GF_Config_Data_Parser $parser ) {
$this->parser = $parser;
}
/**
* Method to handle defining the data array for this config.
*
* @since 2.6
*
* @return array
*/
abstract protected function data();
/**
* Determine if the config should enqueue its data. If should_enqueue() is a method,
* call it and return the result. If not, simply return the (boolean) value of the property.
*
* @since 2.6
*
* @return bool
*/
public function should_enqueue() {
if ( is_callable( $this->should_enqueue ) ) {
return call_user_func( $this->should_enqueue );
}
return $this->should_enqueue;
}
/**
* Get the data for the config, passing it through a filter.
*
* @since 2.6
*
* @return array
*/
public function get_data() {
if ( ( ! defined( 'GFORMS_DOING_MOCK' ) || ! GFORMS_DOING_MOCK ) && ! $this->should_enqueue() ) {
return false;
}
/**
* Allows developers to modify the raw config data being sent to the Config Parser. Useful for
* adding in custom default/mock values for a given entry in the data, as well as modifying
* things like callbacks for dynamic data before it's parsed and localized.
*
* @since 2.6
*
* @param array $data
* @param string $script_to_localize
*
* @return array
*/
$data = apply_filters( 'gform_config_data_' . $this->name(), $this->data(), $this->script_to_localize() );
return $this->parser->parse( $data );
}
/**
* Get the name of the config's object.
*
* @since 2.6
*
* @return string
*/
public function name() {
return $this->name;
}
/**
* Get the $priority for the config.
*
* @since 2.6
*
* @return int
*/
public function priority() {
return $this->priority;
}
/**
* Get the script to localize.
*
* @since 2.6
*
* @return string
*/
public function script_to_localize() {
return $this->script_to_localize;
}
/**
* Get whether the config should override previous values.
*
* @since 2.6
*
* @return bool
*/
public function should_overwrite() {
return $this->overwrite;
}
}

View File

@@ -1,48 +0,0 @@
<?php
namespace Gravity_Forms\Gravity_Forms\Config\Items;
use Gravity_Forms\Gravity_Forms\Config\GF_Config_Collection;
use Gravity_Forms\Gravity_Forms\Config\GF_Config;
use Gravity_Forms\Gravity_Forms\Config\GF_Configurator;
/**
* Config items for Admin I18N
*
* @since 2.6
*/
class GF_Config_Admin_I18n extends GF_Config {
protected $name = 'gform_admin_i18n';
protected $script_to_localize = 'gform_gravityforms_admin_vendors';
/**
* Whether we should enqueue this data.
*
* @since 2.6
*
* @return bool|mixed
*/
public function should_enqueue() {
return is_admin();
}
/**
* Config data.
*
* @return array[]
*/
public function data() {
return array(
// named sub objects that match the admin js file name (camelCased) they are localizing
'formAdmin' => array(
'toggleFeedInactive' => esc_html__( 'Inactive', 'gravityforms' ),
'toggleFeedActive' => esc_html__( 'Active', 'gravityforms' ),
),
'shortcodeUi' => array(
'editForm' => esc_html__( 'Edit Form', 'gravityforms' ),
'insertForm' => esc_html__( 'Insert Form', 'gravityforms' ),
),
);
}
}

View File

@@ -1,40 +0,0 @@
<?php
namespace Gravity_Forms\Gravity_Forms\Config\Items;
use Gravity_Forms\Gravity_Forms\Config\GF_Config_Collection;
use Gravity_Forms\Gravity_Forms\Config\GF_Config;
use Gravity_Forms\Gravity_Forms\Config\GF_Configurator;
/**
* Config items for the Block Editor.
*
* @since 2.6
*/
class GF_Config_Block_Editor extends GF_Config {
protected $name = 'gform_admin_config';
protected $script_to_localize = 'gform_gravityforms_admin_vendors';
/**
* Config data.
*
* @return array[]
*/
public function data() {
return array(
'block_editor' => array(
'data' => array(
'is_block_editor' => \GFCommon::is_block_editor_page(),
),
'i18n' => array(
'insert_gform_block_title' => __( 'Add Block To Page', 'gravityforms' ),
'insert_gform_block_content' => __( 'Click or drag the Gravity Forms Block into the page to insert the form you selected. %1$sLearn More.%2$s', 'gravityforms' ),
),
'urls' => array(
'block_docs' => 'https://docs.gravityforms.com/gravity-forms-gutenberg-block/',
),
)
);
}
}

View File

@@ -1,25 +0,0 @@
<?php
namespace Gravity_Forms\Gravity_Forms\Config\Items;
/**
* Acts as a container for any Global Config data we need to send to both
* the admin and theme side of the ecosystem.
*
* @since 2.7
*/
class GF_Config_Global {
/**
* The data to send to both configs.
*
* @return array
*/
public function data() {
return array(
'hmr_dev' => defined( 'GF_ENABLE_HMR' ) && GF_ENABLE_HMR,
'public_path' => trailingslashit( \GFCommon::get_base_url() ) . 'assets/js/dist/',
);
}
}

View File

@@ -1,59 +0,0 @@
<?php
namespace Gravity_Forms\Gravity_Forms\Config\Items;
use Gravity_Forms\Gravity_Forms\Config\GF_Config_Collection;
use Gravity_Forms\Gravity_Forms\Config\GF_Config;
use Gravity_Forms\Gravity_Forms\Config\GF_Configurator;
/**
* Config items for Theme I18N
*
* @since 2.6
*/
class GF_Config_I18n extends GF_Config {
protected $name = 'gform_i18n';
protected $script_to_localize = 'gform_gravityforms';
/**
* Config data.
*
* @return array[]
*/
public function data() {
return array(
'datepicker' => array(
'days' => array(
'monday' => esc_html__( 'Mo', 'gravityforms' ),
'tuesday' => esc_html__( 'Tu', 'gravityforms' ),
'wednesday' => esc_html__( 'We', 'gravityforms' ),
'thursday' => esc_html__( 'Th', 'gravityforms' ),
'friday' => esc_html__( 'Fr', 'gravityforms' ),
'saturday' => esc_html__( 'Sa', 'gravityforms' ),
'sunday' => esc_html__( 'Su', 'gravityforms' ),
),
'months' => array(
'january' => esc_html__( 'January', 'gravityforms' ),
'february' => esc_html__( 'February', 'gravityforms' ),
'march' => esc_html__( 'March', 'gravityforms' ),
'april' => esc_html__( 'April', 'gravityforms' ),
'may' => esc_html__( 'May', 'gravityforms' ),
'june' => esc_html__( 'June', 'gravityforms' ),
'july' => esc_html__( 'July', 'gravityforms' ),
'august' => esc_html__( 'August', 'gravityforms' ),
'september' => esc_html__( 'September', 'gravityforms' ),
'october' => esc_html__( 'October', 'gravityforms' ),
'november' => esc_html__( 'November', 'gravityforms' ),
'december' => esc_html__( 'December', 'gravityforms' ),
),
'firstDay' => array(
'value' => absint( get_option( 'start_of_week' ) ),
'default' => 1,
),
'iconText' => esc_html__( 'Select date', 'gravityforms' ),
),
);
}
}

View File

@@ -1,34 +0,0 @@
<?php
namespace Gravity_Forms\Gravity_Forms\Config\Items;
use Gravity_Forms\Gravity_Forms\Config\GF_Config;
use Gravity_Forms\Gravity_Forms\Config\GF_Config_Collection;
use Gravity_Forms\Gravity_Forms\Config\GF_Configurator;
/**
* Config items for Multi Legacy Check (mostly just data from a filter).
*
* @since 2.6
*/
class GF_Config_Legacy_Check_Multi extends GF_Config {
protected $name = 'gf_legacy_multi';
protected $script_to_localize = 'gform_gravityforms';
/**
* Config data.
*
* @return array[]
*/
public function data() {
/**
* Allows users to filter the legacy checks for any form on the page.
*
* @since 2.5
*
* @param array
*/
return apply_filters( 'gform_gf_legacy_multi', array() );
}
}

View File

@@ -1,45 +0,0 @@
<?php
namespace Gravity_Forms\Gravity_Forms\Config\Items;
use Gravity_Forms\Gravity_Forms\Config\GF_Config;
use Gravity_Forms\Gravity_Forms\Config\GF_Config_Collection;
use Gravity_Forms\Gravity_Forms\Config\GF_Configurator;
/**
* Config items for Theme Legacy Checks.
*
* @since 2.6
*/
class GF_Config_Legacy_Check extends GF_Config {
protected $name = 'gf_legacy';
protected $script_to_localize = 'gform_layout_editor';
/**
* Determine if the config should enqueue its data.
*
* @since 2.7
*
* @return bool
*/
public function should_enqueue() {
return \GFCommon::is_form_editor();
}
/**
* Config data.
*
* @return array[]
*/
public function data() {
$form = \RGFormsModel::get_form_meta( rgget( 'id' ) );
return array(
'is_legacy' => array(
'value' => \GFCommon::is_legacy_markup_enabled( $form ),
'default' => 0,
),
);
}
}

View File

@@ -1,44 +0,0 @@
<?php
namespace Gravity_Forms\Gravity_Forms\Config\Items;
use Gravity_Forms\Gravity_Forms\Config\GF_Config;
use Gravity_Forms\Gravity_Forms\Config\GF_Configurator;
/**
* Config items for Multifile Strings
*
* @since 2.6
*/
class GF_Config_Multifile extends GF_Config {
protected $script_to_localize = 'gform_gravityforms';
protected $name = 'gform_gravityforms';
/**
* Config data.
*
* @return array[]
*/
public function data() {
return array(
'strings' => array(
'invalid_file_extension' => wp_strip_all_tags( __( 'This type of file is not allowed. Must be one of the following: ', 'gravityforms' ) ),
'delete_file' => wp_strip_all_tags( __( 'Delete this file', 'gravityforms' ) ),
'in_progress' => wp_strip_all_tags( __( 'in progress', 'gravityforms' ) ),
'file_exceeds_limit' => wp_strip_all_tags( __( 'File exceeds size limit', 'gravityforms' ) ),
'illegal_extension' => wp_strip_all_tags( __( 'This type of file is not allowed.', 'gravityforms' ) ),
'max_reached' => wp_strip_all_tags( __( 'Maximum number of files reached', 'gravityforms' ) ),
'unknown_error' => wp_strip_all_tags( __( 'There was a problem while saving the file on the server', 'gravityforms' ) ),
'currently_uploading' => wp_strip_all_tags( __( 'Please wait for the uploading to complete', 'gravityforms' ) ),
'cancel' => wp_strip_all_tags( __( 'Cancel', 'gravityforms' ) ),
'cancel_upload' => wp_strip_all_tags( __( 'Cancel this upload', 'gravityforms' ) ),
'cancelled' => wp_strip_all_tags( __( 'Cancelled', 'gravityforms' ) )
),
'vars' => array(
'images_url' => \GFCommon::get_base_url() . '/images'
)
);
}
}

View File

@@ -1,132 +0,0 @@
<?php
/**
* Handles logic for duplicate submission prevention services.
*
* @package Gravity_Forms\Gravity_Forms\Duplicate_Submissions
*/
namespace Gravity_Forms\Gravity_Forms\Duplicate_Submissions;
/**
* Class GF_Duplicate_Submissions_Handler
*
* @since 2.9.1
*
* Provides functionality for handling duplicate submissions while avoiding multiple
* entries being submitted.
*/
class GF_Duplicate_Submissions_Handler {
/**
* The URL parameter used for redirect protection in Safari.
*/
const SAFARI_REDIRECT_PARAM = 'gf_protect_submission';
/**
* The base URL for this plugin
*
* @var string $base_url.
*/
private $base_url;
/**
* GF_Duplicate_Submissions_Handler constructor.
*
* @param string $base_url The Base URL for this Plugin.
*/
public function __construct( $base_url ) {
$this->base_url = $base_url;
}
/**
* Returns true if duplicate submission protection is enabled. false otherwise.
*
* @returns bool $is_enabled true if duplicate protection is active/enabled. false otherwise
*/
public function is_enabled() {
$form_id = filter_input( INPUT_POST, 'gform_submit', FILTER_SANITIZE_NUMBER_INT );
if ( empty( $form_id ) ) {
return false;
}
/**
* Allows users to disable duplicate submissions protection, either globally
* or on a form-by-form basis.
*
* @since 2.5.15
*
* @param bool Passes a false value by default.
* @param int|string Passes the current form ID.
*/
$is_disabled = gf_apply_filters( array( 'gform_is_disabled_duplicate_submissions_protection', $form_id ), false, $form_id );
return ! $is_disabled;
}
/**
* Enqueue the JS file if this is a form submission configured for duplicate protection.
*/
public function maybe_enqueue_scripts() {
if ( $this->is_enabled() ) {
$min = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG || isset( $_GET['gform_debug'] ) ? '' : '.min';
wp_enqueue_script( 'gform_duplicate_submissions', $this->base_url . "/js/duplicate-submissions{$min}.js", array(), true );
wp_localize_script( 'gform_duplicate_submissions', 'gf_duplicate_submissions', $this->get_localized_script_data() );
}
}
/**
* Get the correct data to localize to the JS file.
*
* @return array
*/
private function get_localized_script_data() {
return array(
'is_gf_submission' => (int) $this->is_valid_submission(),
'safari_redirect_param' => self::SAFARI_REDIRECT_PARAM,
);
}
/**
* Check if the current submission exists, and is valid.
*
* @return bool
*/
private function is_valid_submission() {
$form_id = filter_input( INPUT_POST, 'gform_submit', FILTER_SANITIZE_NUMBER_INT );
if ( empty( $form_id ) || ! class_exists( '\GFFormDisplay' ) ) {
return false;
}
$entry_id = rgars( \GFFormDisplay::$submission, $form_id . '/lead/id' );
if ( empty( $entry_id ) ) {
return false;
}
\GFCommon::log_debug( __METHOD__ . sprintf( '(): form #%d. entry #%d.', $form_id, $entry_id ) );
return true;
}
/**
* Redirect to a $_GET request if we detect a dupe submission from Safari.
*/
public function maybe_handle_safari_redirect() {
if ( rgget( self::SAFARI_REDIRECT_PARAM ) != '1' || ! $this->is_enabled() ) {
return;
}
// Get the submission URL from the $_SERVER, and strip out our redirect param.
$submission_url = filter_input( INPUT_SERVER, 'HTTP_REFERER', FILTER_SANITIZE_URL );
$base_url = esc_url( remove_query_arg( self::SAFARI_REDIRECT_PARAM, $submission_url ) );
// Redirect to the form's page URL as a GET request.
wp_safe_redirect( $base_url, 303 );
exit;
}
}

View File

@@ -1,54 +0,0 @@
<?php
/**
* Service Provider for Duplicate Submission Service
*
* @package Gravity_Forms\Gravity_Forms\Duplicate_Submissions
*/
namespace Gravity_Forms\Gravity_Forms\Duplicate_Submissions;
use Gravity_Forms\Gravity_Forms\GF_Service_Container;
use Gravity_Forms\Gravity_Forms\GF_Service_Provider;
use Gravity_Forms\Gravity_Forms\Util\GF_Util_Service_Provider;
/**
* Class GF_License_Service_Provider
*
* Service provider for the Duplicate Submission Service.
*/
class GF_Duplicate_Submissions_Service_Provider extends GF_Service_Provider {
const GF_DUPLICATE_SUBMISSION_HANDLER = 'gf_duplicate_submission_handler';
/**
* Includes all related files and adds all containers.
*
* @param GF_Service_Container $container Container singleton object.
*/
public function register( GF_Service_Container $container ) {
\GFForms::include_gravity_api();
require_once plugin_dir_path( __FILE__ ) . 'class-gf-duplicate-submissions-handler.php';
$container->add(
self::GF_DUPLICATE_SUBMISSION_HANDLER,
function () {
return new GF_Duplicate_Submissions_Handler( \GFCommon::get_base_url() );
}
);
}
/**
* Initializes service.
*
* @param GF_Service_Container $container Service Container.
*/
public function init( GF_Service_Container $container ) {
parent::init( $container );
$duplicate_submission_handler = $container->get( self::GF_DUPLICATE_SUBMISSION_HANDLER );
add_action( 'gform_enqueue_scripts', array( $duplicate_submission_handler, 'maybe_enqueue_scripts' ) );
add_action( 'wp_loaded', array( $duplicate_submission_handler, 'maybe_handle_safari_redirect' ), 8, 0 );
}
}

View File

@@ -1,147 +0,0 @@
<?php
namespace Gravity_Forms\Gravity_Forms\Editor_Button;
use Gravity_Forms\Gravity_Forms\Config\GF_Config_Service_Provider;
use Gravity_Forms\Gravity_Forms\Editor_Button\Config\GF_Editor_Config;
use Gravity_Forms\Gravity_Forms\Editor_Button\Dom\GF_Editor_Button;
use Gravity_Forms\Gravity_Forms\Editor_Button\Endpoints\GF_Editor_Save_Editor_Settings;
use Gravity_Forms\Gravity_Forms\GF_Service_Container;
use Gravity_Forms\Gravity_Forms\GF_Service_Provider;
/**
* Class GF_Editor_Service_Provider
*
* Service provider for the Embed Form Service.
*
* @package Gravity_Forms\Gravity_Forms\Editor_Button;
*/
class GF_Editor_Service_Provider extends GF_Service_Provider {
// Configs
const EDITOR_CONFIG = 'editor_config';
const ENDPOINTS_CONFIG = 'editor_endpoints_config';
// DOM
const DOM_EDITOR_BUTTON = 'dom_editor_button';
/**
* Array mapping config class names to their container ID.
*
* @since 2.8
*
* @var string[]
*/
protected $configs = array(
self::EDITOR_CONFIG => GF_Editor_Config::class,
);
/**
* Register services to the container.
*
* @since 2.6
*
* @param GF_Service_Container $container
*/
public function register( GF_Service_Container $container ) {
// Configs
require_once( plugin_dir_path( __FILE__ ) . '/config/class-gf-editor-config.php' );
// Dom
require_once( plugin_dir_path( __FILE__ ) . '/dom/class-gf-editor-button.php' );
// Endpoints
require_once( plugin_dir_path( __FILE__ ) . '/endpoints/class-gf-editor-save-editor-settings.php' );
$container->add( self::ENDPOINTS_CONFIG, function () {
return new GF_Editor_Save_Editor_Settings();
} );
$this->add_configs( $container );
$this->dom( $container );
}
/**
* Initialize any actions or hooks.
*
* @since 2.6
*
* @param GF_Service_Container $container
*
* @return void
*/
public function init( GF_Service_Container $container ) {
add_action( 'gform_after_toolbar_buttons', function () use ( $container ) {
$container->get( self::DOM_EDITOR_BUTTON )->output_button();
} );
add_action( 'wp_ajax_' . GF_Editor_Save_Editor_Settings::ACTION_NAME, function () use ( $container ) {
$container->get( self::ENDPOINTS_CONFIG )->handle();
} );
}
/**
* For each config defined in $configs, instantiate and add to container.
*
* @since 2.6
*
* @param GF_Service_Container $container
*
* @return void
*/
private function add_configs( GF_Service_Container $container ) {
foreach ( $this->configs as $name => $class ) {
$container->add( $name, function () use ( $container, $class ) {
return new $class( $container->get( GF_Config_Service_Provider::DATA_PARSER ) );
} );
$container->get( GF_Config_Service_Provider::CONFIG_COLLECTION )->add_config( $container->get( $name ) );
}
}
/**
* Register DOM-related services.
*
* @since 2.6
*
* @param GF_Service_Container $container
*
* @return void
*/
private function dom( GF_Service_Container $container ) {
$container->add( self::DOM_EDITOR_BUTTON, function() {
return new GF_Editor_Button();
});
}
/**
* Determine if the compact view is enabled for the given form and user.
*
* @since 2.8
*
* @param int $user_id The user ID.
* @param int $form_id The form ID.
*
* @return bool
*/
public static function is_compact_view_enabled( $user_id, $form_id ) {
$compact_view = get_user_meta( $user_id, 'gform_compact_view_' . $form_id, true );
return $compact_view === 'enable';
}
/**
* Determine if the field ID view in compact view is enabled for the given form and user.
*
* @since 2.8
*
* @param int $user_id The user ID.
* @param int $form_id The form ID.
*
* @return bool
*/
public static function is_field_id_enabled( $user_id, $form_id ) {
$field_id = get_user_meta( $user_id, 'gform_compact_view_show_id_' . $form_id, true );
return $field_id === 'enable';
}
}

View File

@@ -1,85 +0,0 @@
<?php
namespace Gravity_Forms\Gravity_Forms\Editor_Button\Config;
use Gravity_Forms\Gravity_Forms\Config\GF_Config;
use Gravity_Forms\Gravity_Forms\Editor_Button\GF_Editor_Service_Provider;
use Gravity_Forms\Gravity_Forms\Editor_Button\Endpoints\GF_Editor_Save_Editor_Settings;
/**
* Config items for the Editor Settings Button
*
* @since 2.8
*/
class GF_Editor_Config extends GF_Config {
protected $name = 'gform_admin_config';
protected $script_to_localize = 'gform_gravityforms_admin_vendors';
/**
* Determine if the config should enqueue its data.
*
* @since 2.8
*
* @return bool
*/
public function should_enqueue() {
return \GFCommon::is_form_editor();
}
/**
* Config data.
*
* @return array[]
*/
public function data() {
return array(
'components' => array(
'editor_button' => array(
'i18n' => array(
'title' => esc_html__( 'Editor Preferences', 'gravityforms' ),
'closeButtonAriaLabel' => esc_html__( 'Close button', 'gravityforms' ),
'description' => esc_html__( 'Change options related to the form editor.', 'gravityforms' ),
'compactToggleLabel' => esc_html__( 'Compact View', 'gravityforms' ),
'compactToggleText' => esc_html__( 'Simplify the preview of form fields for a more streamlined editing experience.', 'gravityforms' ),
'idToggleLabel' => esc_html__( 'Show Field IDs', 'gravityforms' ),
'idToggleText' => esc_html__( 'Show the ID of each field in Compact View.', 'gravityforms' ),
),
'endpoints' => $this->get_endpoints(),
'compactViewEnabled' => GF_Editor_Service_Provider::is_compact_view_enabled( get_current_user_id(), rgget( 'id' ) ),
'fieldIdEnabled' => GF_Editor_Service_Provider::is_field_id_enabled( get_current_user_id(), rgget( 'id' ) ),
'form' => rgget( 'id' ),
),
'dropdown_menu' => array(
'i18n' => array(
'duplicateButtonLabel' => esc_html__( 'Duplicate', 'gravityforms' ),
'deleteButtonLabel' => esc_html__( 'Delete', 'gravityforms' ),
'dropdownButtonLabel' => esc_html__( 'Dropdown menu button', 'gravityforms' ),
),
),
),
);
}
/**
* Gets the endpoints for saving the compact view settings.
*
* @since 2.8
*
* @return \array[][]
*/
private function get_endpoints() {
return array(
'save_editor_settings' => array(
'action' => array(
'value' => GF_Editor_Save_Editor_Settings::ACTION_NAME,
'default' => 'mock_endpoint',
),
'nonce' => array(
'value' => wp_create_nonce( GF_Editor_Save_Editor_Settings::ACTION_NAME ),
'default' => 'nonce',
),
),
);
}
}

View File

@@ -1,30 +0,0 @@
<?php
namespace Gravity_Forms\Gravity_Forms\Editor_Button\Dom;
/**
* Handle outputting the Embed Button in the UI.
*
* @since 2.6
*
* @package Gravity_Forms\Gravity_Forms\Embed_Form\Dom
*/
class GF_Editor_Button {
/**
* Output the HTML for the Embed Button.
*/
public function output_button() {
?>
<button
data-js="editor-flyout-trigger"
class="gform-button gform-button--icon-white gform-button--icon-editor"
aria-label="<?php esc_attr_e( 'Open editor preferences', 'gravityforms' ); ?>"
title="<?php esc_attr_e( 'Open editor preferences', 'gravityforms' ); ?>"
>
<i class="gform-icon gform-icon--cog gform-button__icon" aria-hidden="true"></i>
</button>
<?php
}
}

View File

@@ -1,38 +0,0 @@
<?php
namespace Gravity_Forms\Gravity_Forms\Editor_Button\Endpoints;
use Gravity_Forms\Gravity_Forms\Config\GF_Config;
/**
* AJAX Endpoint for saving the compact view settings.
*
* @since 2.8
*
* @package Gravity_Forms\Gravity_Forms\Editor_Button\Endpoints
*/
class GF_Editor_Save_Editor_Settings {
// Strings
const ACTION_NAME = 'gf_save_editor_settings';
/**
* Handle the AJAX request.
*
* @since 2.8
*
* @return void
*/
public function handle() {
check_ajax_referer( self::ACTION_NAME );
$form = intval( rgpost( 'form' ) );
$user = get_current_user_id();
$name = rgpost( 'name' );
$value = rgpost( 'value' );
$value = ( $value == 'enable' ) ? 'enable' : 'disable';
update_user_meta( $user, 'gform_' . $name . '_' . $form, $value );
}
}

View File

@@ -1,153 +0,0 @@
<?php
namespace Gravity_Forms\Gravity_Forms\Embed_Form;
use Gravity_Forms\Gravity_Forms\Config\GF_Config_Service_Provider;
use Gravity_Forms\Gravity_Forms\Embed_Form\Config\GF_Embed_Config;
use Gravity_Forms\Gravity_Forms\Embed_Form\Config\GF_Embed_Config_I18N;
use Gravity_Forms\Gravity_Forms\Embed_Form\Config\GF_Embed_Endpoints_Config;
use Gravity_Forms\Gravity_Forms\Embed_Form\Dom\GF_Embed_Button;
use Gravity_Forms\Gravity_Forms\Embed_Form\Endpoints\GF_Embed_Endpoint_Create_With_Block;
use Gravity_Forms\Gravity_Forms\Embed_Form\Endpoints\GF_Embed_Endpoint_Get_Posts;
use Gravity_Forms\Gravity_Forms\GF_Service_Container;
use Gravity_Forms\Gravity_Forms\GF_Service_Provider;
/**
* Class GF_Embed_Service_Provider
*
* Service provider for the Embed Form Service.
*
* @package Gravity_Forms\Gravity_Forms\Embed_Form;
*/
class GF_Embed_Service_Provider extends GF_Service_Provider {
// Configs
const EMBED_CONFIG = 'embed_config';
const EMBED_CONFIG_I18N = 'embed_config_i18n';
const EMBED_CONFIG_ENDPOINTS = 'embed_config_endpoints';
// Endpoints
const ENDPOINT_GET_POSTS = 'endpoint_get_posts';
const ENDPOINT_CREATE_WITH_BLOCK = 'endpoint_create_with_block';
// DOM
const DOM_EMBED_BUTTON = 'dom_embed_button';
// Strings
const ADD_BLOCK_PARAM = 'gfAddBlock';
/**
* Array mapping config class names to their container ID.
*
* @since 2.6
*
* @var string[]
*/
protected $configs = array(
self::EMBED_CONFIG => GF_Embed_Config::class,
self::EMBED_CONFIG_I18N => GF_Embed_Config_I18N::class,
self::EMBED_CONFIG_ENDPOINTS => GF_Embed_Endpoints_Config::class,
);
/**
* Register services to the container.
*
* @since 2.6
*
* @param GF_Service_Container $container
*/
public function register( GF_Service_Container $container ) {
// Configs
require_once( plugin_dir_path( __FILE__ ) . '/config/class-gf-embed-config.php' );
require_once( plugin_dir_path( __FILE__ ) . '/config/class-gf-embed-config-i18n.php' );
require_once( plugin_dir_path( __FILE__ ) . '/config/class-gf-embed-endpoints-config.php' );
// Endpoints
require_once( plugin_dir_path( __FILE__ ) . '/endpoints/class-gf-embed-endpoint-get-posts.php' );
require_once( plugin_dir_path( __FILE__ ) . '/endpoints/class-gf-embed-endpoint-create-with-block.php' );
// Dom
require_once( plugin_dir_path( __FILE__ ) . '/dom/class-gf-embed-button.php' );
$this->add_configs( $container );
$this->add_endpoints( $container );
$this->dom( $container );
}
/**
* Initiailize any actions or hooks.
*
* @since 2.6
*
* @param GF_Service_Container $container
*
* @return void
*/
public function init( GF_Service_Container $container ) {
add_action( 'wp_ajax_' . GF_Embed_Endpoint_Get_Posts::ACTION_NAME, function () use ( $container ) {
$container->get( self::ENDPOINT_GET_POSTS )->handle();
} );
add_action( 'wp_ajax_' . GF_Embed_Endpoint_Create_With_Block::ACTION_NAME, function () use ( $container ) {
$container->get( self::ENDPOINT_CREATE_WITH_BLOCK )->handle();
} );
add_action( 'gform_before_toolbar_buttons', function () use ( $container ) {
$container->get( self::DOM_EMBED_BUTTON )->output_button();
} );
}
/**
* For each config defined in $configs, instantiate and add to container.
*
* @since 2.6
*
* @param GF_Service_Container $container
*
* @return void
*/
private function add_configs( GF_Service_Container $container ) {
foreach ( $this->configs as $name => $class ) {
$container->add( $name, function () use ( $container, $class ) {
return new $class( $container->get( GF_Config_Service_Provider::DATA_PARSER ) );
} );
$container->get( GF_Config_Service_Provider::CONFIG_COLLECTION )->add_config( $container->get( $name ) );
}
}
/**
* Register AJAX endpoints for the Embed UI.
*
* @since 2.6
*
* @param GF_Service_Container $container
*
* @return void
*/
private function add_endpoints( GF_Service_Container $container ) {
$container->add( self::ENDPOINT_GET_POSTS, function () use ( $container ) {
return new GF_Embed_Endpoint_Get_Posts();
} );
$container->add( self::ENDPOINT_CREATE_WITH_BLOCK, function () use ( $container ) {
return new GF_Embed_Endpoint_Create_With_Block();
} );
}
/**
* Register DOM-related services.
*
* @since 2.6
*
* @param GF_Service_Container $container
*
* @return void
*/
private function dom( GF_Service_Container $container ) {
$container->add( self::DOM_EMBED_BUTTON, function() {
return new GF_Embed_Button();
});
}
}

View File

@@ -1,66 +0,0 @@
<?php
namespace Gravity_Forms\Gravity_Forms\Embed_Form\Config;
use Gravity_Forms\Gravity_Forms\Config\GF_Config;
/**
* Config items for the Embed Form I18N
*
* @since 2.6
*/
class GF_Embed_Config_I18N extends GF_Config {
protected $name = 'gform_admin_config';
protected $script_to_localize = 'gform_gravityforms_admin_vendors';
/**
* Determine if the config should enqueue its data.
*
* @since 2.6.2
*
* @return bool
*/
public function should_enqueue() {
return \GFCommon::is_form_editor();
}
/**
* Config data.
*
* @return array[]
*/
public function data() {
return array(
'components' => array(
'embed_form' => array(
'i18n' => array(
'title' => esc_html__( 'Embed Form', 'gravityforms' ),
'id' => esc_html__( 'Form ID: %s', 'gravityforms' ),
'add_title' => esc_html__( 'Add to Existing Content', 'gravityforms' ),
'add_post_type_choice_label' => esc_html__( '%1$sAdd to Existing Content:%2$s %3$s', 'gravityforms' ),
'add_dropdown_placeholder' => esc_html__( 'Select a %s', 'gravityforms' ),
'add_trigger_aria_text' => esc_html__( 'Select a post', 'gravityforms' ),
'add_search_aria_text' => esc_html__( 'Search all %ss', 'gravityforms' ),
'add_button_label' => esc_html__( 'Insert Form', 'gravityforms' ),
'create_title' => esc_html__( 'Create New', 'gravityforms' ),
'create_post_type_choice_label' => esc_html__( '%1$sCreate New:%2$s %3$s', 'gravityforms' ),
'create_placeholder' => esc_html__( 'Enter %s Name', 'gravityforms' ),
'create_button_label' => esc_html__( 'Create', 'gravityforms' ),
'dialog_title' => esc_html__( 'Unsaved Changes', 'gravityforms' ),
'dialog_content' => esc_html__( 'Oops! You have unsaved changes in the form, before you can continue with embedding it please save your changes.', 'gravityforms' ),
'dialog_confirm_text' => esc_html__( 'Save Changes', 'gravityforms' ),
'dialog_confirm_saving' => esc_html__( 'Saving', 'gravityforms' ),
'dialog_cancel_text' => esc_html__( 'Cancel', 'gravityforms' ),
'dialog_close_title' => esc_html__( 'Close this dialog and return to form editor.', 'gravityforms' ),
'shortcode_title' => esc_html__( 'Not Using the Block Editor?', 'gravityforms' ),
'shortcode_description' => esc_html__( 'Copy and paste the shortcode within your page builder.', 'gravityforms' ),
'shortcode_button_label' => esc_html__( 'Copy Shortcode', 'gravityforms' ),
'shortcode_button_copied' => esc_html__( 'Copied', 'gravityforms' ),
'shortcode_helper' => esc_html__( '%1$sLearn more%2$s about the shortcode.', 'gravityforms' ),
),
),
),
);
}
}

View File

@@ -1,234 +0,0 @@
<?php
namespace Gravity_Forms\Gravity_Forms\Embed_Form\Config;
use Gravity_Forms\Gravity_Forms\Config\GF_Config;
/**
* Config items for the Embed Form UI.
*
* @since 2.6
*/
class GF_Embed_Config extends GF_Config {
protected $name = 'gform_admin_config';
protected $script_to_localize = 'gform_gravityforms_admin_vendors';
/**
* Determine if the config should enqueue its data.
*
* @since 2.6.2
*
* @return bool
*/
public function should_enqueue() {
return \GFCommon::is_form_editor();
}
/**
* Config data.
*
* @return array[]
*/
public function data() {
return array(
'components' => array(
'embed_form' => array(
'urls' => $this->get_urls(),
'data' => array(
'form_id' => array(
'value' => rgget( 'id' ),
'default' => 1,
),
'post_types' => array(
'value' => $this->get_available_post_types(),
'default' => $this->placeholder_post_types(),
),
'items' => array(
'value' => $this->get_items_by_type(),
'default' => $this->placeholder_items(),
),
),
),
),
);
}
/**
* Get the various URLs for the Embed UI.
*
* @since 2.6
*
* @return array
*/
private function get_urls() {
$edit_link = '';
$post_type_object = get_post_type_object( 'page' );
if ( ! empty( $post_type_object->_edit_link ) ) {
$edit_link = admin_url( str_replace( '%d', '%1$s', $post_type_object->_edit_link ) . '&action=edit' );
}
/**
* Allows the edit post link to be customized.
*
* @since 2.6.2
*
* @param string $link The edit link. Use %1$s as the placeholder for the ID.
*/
$edit_link = apply_filters( 'gform_embed_edit_post_link', $edit_link );
return [
'edit_post' => [
'value' => $edit_link,
'default' => 'https://gravity.loc/wp-admin/post.php?post=%1$s&action=edit',
],
'shortcode_docs' => 'https://docs.gravityforms.com/shortcodes/',
];
}
/**
* Get the Post Types data for the Embed UI.
*
* @since 2.6
*
* @return array
*/
private function get_available_post_types() {
$types = array(
array(
'slug' => 'page',
'label' => get_post_type_object( 'page' )->labels->singular_name,
),
array(
'slug' => 'post',
'label' => get_post_type_object( 'post' )->labels->singular_name,
),
);
/**
* Allows users to modify the post types sent as selectable options in the Embed UI.
*
* @since 2.6
*
* @param array $types
*
* @return array
*/
return apply_filters( 'gform_embed_post_types', $types );
}
/**
* Get the items to localize for each post type.
*
* @since 2.6
*
* @return array
*/
private function get_items_by_type() {
$types = $this->get_available_post_types();
$data = array();
foreach ( $types as $type ) {
$slug = $type['slug'];
$label = $type['label'];
$items = get_posts( array( 'post_type' => $slug, 'posts_per_page' => 5 ) );
array_walk( $items, function ( &$item ) {
$item = array(
'value' => $item->ID,
'label' => $item->post_title,
);
} );
$data[ $slug ]['entries'] = $items;
$data[ $slug ]['count'] = $this->get_total_posts_by_type( $slug );
}
return $data;
}
/**
* Get the totals for the given post type.
*
* @since 2.6
*
* @param string $type - The Post Type to query for.
*
* @return array
*/
private function get_total_posts_by_type( $type ) {
$args = array(
'post_type' => $type,
'post_status' => 'publish',
);
$query = new \WP_Query( $args );
return $query->found_posts;
}
/**
* Get the placeholder post type values for use in Mocks.
*
* @since 2.6
*
* @return array
*/
private function placeholder_post_types() {
return array(
array( 'slug' => 'page', 'label' => __( 'Page', 'gravityforms' ) ),
array( 'slug' => 'post', 'label' => __( 'Post', 'gravityforms' ) ),
);
}
/**
* Get the placeholder post items for use in Mocks.
*
* @since 2.6
*
* @return array
*/
private function placeholder_items() {
return array(
'post' => array(
'count' => 2,
'entries' => array(
array(
'value' => 1,
'label' => 'Post One',
),
array(
'value' => 2,
'label' => 'Post Two',
),
),
),
'page' => array(
'count' => 25,
'entries' => array(
array(
'value' => 3,
'label' => 'Page Three',
),
array(
'value' => 4,
'label' => 'Page Four',
),
array(
'value' => 5,
'label' => 'Page Five',
),
array(
'value' => 6,
'label' => 'Page Six',
),
array(
'value' => 7,
'label' => 'Page Seven',
),
),
)
);
}
}

View File

@@ -1,82 +0,0 @@
<?php
namespace Gravity_Forms\Gravity_Forms\Embed_Form\Config;
use Gravity_Forms\Gravity_Forms\Config\GF_Config;
use Gravity_Forms\Gravity_Forms\Embed_Form\Endpoints\GF_Embed_Endpoint_Create_With_Block;
use Gravity_Forms\Gravity_Forms\Embed_Form\Endpoints\GF_Embed_Endpoint_Get_Posts;
/**
* Config items for the Embed Forms REST Endpoints.
*
* @since 2.6
*/
class GF_Embed_Endpoints_Config extends GF_Config {
protected $script_to_localize = 'gform_gravityforms_admin_vendors';
protected $name = 'gform_admin_config';
protected $overwrite = false;
/**
* Determine if the config should enqueue its data.
*
* @since 2.6.2
*
* @return bool
*/
public function should_enqueue() {
return \GFCommon::is_form_editor();
}
/**
* Config data.
*
* @return array[]
*/
public function data() {
return array(
'components' => array(
'embed_form' => array(
'endpoints' => $this->get_endpoints(),
),
),
);
}
/**
* Get the various endpoints for the Embed UI.
*
* @since 2.6
*
* @return array
*/
private function get_endpoints() {
return array(
// Endpoint to get posts for typeahead
'get_posts' => array(
'action' => array(
'value' => 'gf_embed_query_posts',
'default' => 'mock_endpoint',
),
'nonce' => array(
'value' => wp_create_nonce( GF_Embed_Endpoint_Get_Posts::ACTION_NAME ),
'default' => 'nonce',
)
),
// Endpoint to create a new page with our block inserted.
'create_post_with_block' => array(
'action' => array(
'value' => GF_Embed_Endpoint_Create_With_Block::ACTION_NAME,
'default' => 'mock_endpoint',
),
'nonce' => array(
'value' => wp_create_nonce( GF_Embed_Endpoint_Create_With_Block::ACTION_NAME ),
'default' => 'nonce',
)
)
);
}
}

View File

@@ -1,26 +0,0 @@
<?php
namespace Gravity_Forms\Gravity_Forms\Embed_Form\Dom;
/**
* Handle outputting the Embed Button in the UI.
*
* @since 2.6
*
* @package Gravity_Forms\Gravity_Forms\Embed_Form\Dom
*/
class GF_Embed_Button {
/**
* Output the HTML for the Embed Button.
*/
public function output_button() {
?>
<button data-js="embed-flyout-trigger" class="gform-button gform-button--white gform-button--icon-leading">
<i class="gform-button__icon gform-icon gform-icon--embed-alt"></i>
<?php _e( 'Embed', 'gravityforms' ); ?>
</button>
<?php
}
}

View File

@@ -1,68 +0,0 @@
<?php
namespace Gravity_Forms\Gravity_Forms\Embed_Form\Endpoints;
/**
* AJAX Endpoint for creating a new post with a specific block already added.
*
* @since 2.6
*
* @package Gravity_Forms\Gravity_Forms\Embed_Form\Endpoints
*/
class GF_Embed_Endpoint_Create_With_Block {
// Strings
const ACTION_NAME = 'gf_embed_create_post_with_block';
// Request Params
const PARAM_FORM_ID = 'form_id';
const PARAM_POST_TYPE = 'post_type';
const PARAM_POST_TITLE = 'post_title';
/**
* Handle the AJAX request.
*
* @since 2.6
*
* @return void
*/
public function handle() {
check_ajax_referer( self::ACTION_NAME );
$post_type = rgpost( self::PARAM_POST_TYPE );
$form_id = rgpost( self::PARAM_FORM_ID );
$post_title = rgpost( self::PARAM_POST_TITLE );
if ( empty( $post_type ) || empty( $form_id ) ) {
wp_send_json_error( 'Request must include a post_type and form_id.', 400 );
}
$post_data = array(
'post_title' => $post_title,
'post_type' => $post_type,
'post_content' => $this->get_content_for_form( $form_id ),
);
$new_id = wp_insert_post( $post_data );
wp_send_json_success( array( 'ID' => $new_id ) );
}
/**
* Get the properly-formatted comment string for the block we're inserting.
*
* @since 2.6
*
* @param $form_id
*
* @return string
*/
private function get_content_for_form( $form_id ) {
$attrs = array(
'formId' => $form_id
);
return get_comment_delimited_block_content( 'gravityforms/form', $attrs, '' );
}
}

View File

@@ -1,69 +0,0 @@
<?php
namespace Gravity_Forms\Gravity_Forms\Embed_Form\Endpoints;
/**
* AJAX Endpoint for getting posts based on search params.
*
* @since 2.6
*
* @package Gravity_Forms\Gravity_Forms\Embed_Form\Endpoints
*/
class GF_Embed_Endpoint_Get_Posts {
// Strings
const ACTION_NAME = 'gf_embed_query_posts';
// Parameters
const PARAM_OFFSET = 'offset';
const PARAM_COUNT = 'count';
const PARAM_STATUS = 'status';
const PARAM_SEARCH = 'search';
const PARAM_POST_TYPE = 'post_type';
// Defaults
const DEFAULT_OFFSET = 0;
const DEFAULT_COUNT = 10;
const DEFAULT_STATUS = 'publish';
const DEFAULT_SEARCH = '';
const DEFAULT_POST_TYPE = 'post';
/**
* Handle the AJAX request.
*
* @since 2.6
*
* @return void
*/
public function handle() {
check_ajax_referer( self::ACTION_NAME );
$offset = rgpost( self::PARAM_OFFSET ) ? rgpost( self::PARAM_OFFSET ) : self::DEFAULT_OFFSET;
$count = rgpost( self::PARAM_COUNT ) ? rgpost( self::PARAM_COUNT ) : self::DEFAULT_COUNT;
$status = rgpost( self::PARAM_STATUS ) ? rgpost( self::PARAM_STATUS ) : self::DEFAULT_STATUS;
$search = rgpost( self::PARAM_SEARCH ) ? rgpost( self::PARAM_SEARCH ) : self::DEFAULT_SEARCH;
$post_type = rgpost( self::PARAM_POST_TYPE ) ? rgpost( self::PARAM_POST_TYPE ) : self::DEFAULT_POST_TYPE;
$args = array(
'post_type' => $post_type,
'post_status' => $status,
'posts_per_page' => $count,
'offset' => $offset,
's' => $search,
);
$query = new \WP_Query( $args );
$posts = $query->get_posts();
array_walk( $posts, function ( &$post ) {
$post = array(
'value' => $post->ID,
'label' => $post->post_title,
);
} );
wp_send_json_success( $posts );
}
}

View File

@@ -1,224 +0,0 @@
<?php
/**
* Handles logic for adjusting Gravity Forms to different environment configurations.
*
* @package Gravity_Forms\Gravity_Forms\Environment_Config
*/
namespace Gravity_Forms\Gravity_Forms\Environment_Config;
/**
* Class GF_Environment_Config_Handler
*
* @since 2.6.7
*
* Provides functionality for handling environment configuration options.
*/
class GF_Environment_Config_Handler {
/**
* Provides caching service.
*
* @var \GFCache $cache
*/
protected $cache;
/**
* GF_Environment_Config_Handler constructor.
*
* @since 2.6.7
*
* @param \GFCache $cache Provides caching service.
*/
public function __construct( $cache ) {
$this->cache = $cache;
}
/**
* Gets an environment setting from wp_options.
*
* @since 2.6.7
*
* @param string $name The environment setting name. Don't include the "gf_env_" prefix.
* @param mixed $default Default value to be returned if option is not set.
*
* @return mixed
*/
public function get_environment_setting( $name, $default = false ) {
$option_name = "gf_env_{$name}";
$setting = $this->cache->get( $option_name, $found );
if ( ! $found ) {
$setting = get_option( $option_name, $default );
$this->cache->set( $option_name, $setting );
}
return $setting;
}
/**
* Gets the license_key config value.
*
* @since 2.6.7
*
* @return string The license key config.
*/
public function get_license_key() {
return $this->get_environment_setting( 'license_key', false );
}
/**
* Gets the hide_license config value.
*
* @since 2.6.7
*
* @return bool Returns true if license is supposed to be hidden from the UI, false otherwise.
*/
public function get_hide_license() {
return (bool) $this->get_environment_setting( 'hide_license', false );
}
/**
* Gets the hide_background_updates config value.
*
* @since 2.6.9
*
* @return bool Returns true if the background updates setting is supposed to be hidden from the UI. Returns false otherwise.
*/
public function get_hide_background_updates() {
return (bool) $this->get_environment_setting( 'hide_background_updates', false );
}
/**
* Gets the hide_install_wizard config value.
*
* @since 2.6.7
*
* @return bool Returns true if install wizard is supposed to be hidden. Returns false otherwise.
*/
public function get_hide_install_wizard() {
return (bool) $this->get_environment_setting( 'hide_setup_wizard', false );
}
/**
* Gets the hide_update_message config value.
*
* @since 2.6.7
*
* @return bool Returns true if install wizard is supposed to be hidden. Returns false otherwise.
*/
public function get_hide_update_message() {
return (bool) $this->get_environment_setting( 'hide_update_message', false );
}
/**
* Gets the support_url config value.
*
* @since 2.6.7
*
* @return string The support link config value.
*/
public function get_support_url() {
return $this->get_environment_setting( 'support_url', 'https://www.gravityforms.com/open-support-ticket/' );
}
/**
* Gets the unregistered_license_message config value.
*
* @since 2.6.7
*
* @return string The message to be displayed when the license is unregistered.
*/
public function get_unregistered_license_message() {
return $this->get_environment_setting( 'unregistered_license_message' );
}
/**
* Target of the pre_option_gform_pending_installation filter. Bypasses the installation wizard by returning 0 for the gform_pending_installation option.
*
* @hook pre_option_gform_pending_installation 10, 1
*
* @return int Returns 0 if the install wizard is set to be hidden by environment settings. Otherwise return false so that option is not overridden.
*/
public function maybe_override_gform_pending_installation() {
// If environment config is set to hide install wizard, override gform_pending_intallation option with 0. Otherwise, use existing option.
$hide_install_wizard = $this->get_hide_install_wizard();
return $hide_install_wizard ? 0 : false;
}
/**
* Maybe hides the automatic update message on the plugin's page.
*
* @since 2.6.8
*/
public function maybe_hide_plugin_page_message() {
if ( $this->get_hide_update_message() ) {
remove_filter( 'transient_update_plugins', array( 'GFForms', 'check_update' ) );
remove_filter( 'site_transient_update_plugins', array( 'GFForms', 'check_update' ) );
}
}
/**
* Maybe hides the automatic update message on the Update page.
*
* @since 2.6.8
*
* @hook gform_updates_list, 20
*
* @param array $updates Updates array being filtered.
*/
public function maybe_hide_update_page_message( $updates ) {
if ( ! $this->get_hide_update_message() ) {
return $updates;
}
foreach ( $updates as & $update ) {
if ( $update['slug'] == 'gravityforms' ) {
$update['latest_version'] = '';
}
}
return $updates;
}
/**
* Target of the pre_option_rg_gforms_key filter. Uses the license key configured by the environment settings if one is set.
*
* @hook pre_option_rg_gforms_key 10, 1
*
* @since 2.6.7
*
* @return string Returns the environment license key if one is set. If not set, return false so that value is not overridden.
*/
public function maybe_override_rg_gforms_key() {
// Use environment license key if one is set. Otherwise, use rg_gforms_key option.
$env_license_key = $this->get_license_key();
return $env_license_key !== false ? $env_license_key : false;
}
/**
* Target of the gform_plugin_settings_fields filter. Removes sections from the settings page that are configured to be hidden.
*
* @since 2.6.9
*
* @param array $fields The settings fields to be filtered.
*
* @return array Returns the filtered $fields array.
*/
public function maybe_hide_setting( $fields ) {
if ( $this->get_hide_license() ) {
unset( $fields['license_key'] );
unset( $fields['license_key_details'] );
}
if ( $this->get_hide_background_updates() ) {
unset( $fields['background_updates'] );
}
return $fields;
}
}

View File

@@ -1,64 +0,0 @@
<?php
namespace Gravity_Forms\Gravity_Forms\Environment_Config;
use Gravity_Forms\Gravity_Forms\GF_Service_Container;
use Gravity_Forms\Gravity_Forms\GF_Service_Provider;
use Gravity_Forms\Gravity_Forms\Util\GF_Util_Service_Provider;
/**
* Class GF_Environment_Config_Service_Provider
*
* Service provider for the Environment_Config Service.
*
* @package Gravity_Forms\Gravity_Forms\Environment_Config;
*/
class GF_Environment_Config_Service_Provider extends GF_Service_Provider {
const GF_ENVIRONMENT_CONFIG_HANDLER = 'gf_environment_config_handler';
/**
* Register services to the container.
*
* @since 2.7
*
* @param GF_Service_Container $container Service Container.
*/
public function register( GF_Service_Container $container ) {
require_once plugin_dir_path( __FILE__ ) . 'class-gf-environment-config-handler.php';
$container->add(
self::GF_ENVIRONMENT_CONFIG_HANDLER,
function () use ( $container ) {
return new GF_Environment_Config_Handler( $container->get( GF_Util_Service_Provider::GF_CACHE ) );
}
);
}
/**
* Initiailize any actions or hooks.
*
* @since 2.7
*
* @param GF_Service_Container $container Service Container.
*
* @return void
*/
public function init( GF_Service_Container $container ) {
$handler = $container->get( self::GF_ENVIRONMENT_CONFIG_HANDLER );
// Gets environment license key.
add_filter( 'pre_option_rg_gforms_key', array( $handler, 'maybe_override_rg_gforms_key' ) );
// Maybe bypass installation wizard.
add_filter( 'pre_option_gform_pending_installation', array( $handler, 'maybe_override_gform_pending_installation' ) );
// Maybe hides license key setting and license key details.
add_filter( 'gform_plugin_settings_fields', array( $handler, 'maybe_hide_setting' ) );
// Maybe hide plugin auto update messages.
add_filter( 'init', array( $handler, 'maybe_hide_plugin_page_message' ), 20 );
add_filter( 'gform_updates_list', array( $handler, 'maybe_hide_update_page_message' ), 20 );
}
}

View File

@@ -1,36 +0,0 @@
<?php
namespace Gravity_Forms\Gravity_Forms\External_API;
/**
* Class GF_API_Connector
*
* An abstraction allowing us to create codified API Connector classes with a distinct
* strategy for each one, and a standardized Cache mechanism. This separates the actually
* communication logic from the class which calls it, allowing better testability.
*
* @package Gravity_Forms\Gravity_Forms\External_API
*
* @since 2.5
*/
abstract class GF_API_Connector {
protected $strategy;
/**
* @var \GFCache $cache
*/
protected $cache;
/**
* GF_API_Connector constructor.
*
* @param $strategy The strategy class used to actually communicate with the API.
* @param $cache The cache class used for caching results and other operations.
*/
public function __construct( $strategy, $cache ) {
$this->strategy = $strategy;
$this->cache = $cache;
}
}

View File

@@ -1,218 +0,0 @@
<?php
namespace Gravity_Forms\Gravity_Forms\External_API;
/**
* Class GF_API_Response
*
* An abstracted Response class used to standardize the responses we send back from an API Connector. Includes
* standardized serialization and JSON methods to support saving the class to the Database.
*
* @since 2.5
*
* @package Gravity_Forms\Gravity_Forms\External_API
*/
abstract class GF_API_Response implements \JsonSerializable, \Serializable {
/**
* The data for this response.
*
* @var array $data
*/
protected $data = array();
/**
* The status for this response.
*
* @var array $status
*/
protected $status = array();
/**
* The errors (if any) for this response.
*
* @var array $errors
*/
protected $errors = array();
/**
* The meta data (if any) for this response.
*
* @var array $meta
*/
protected $meta = array();
/**
* Set the status for the response.
*
* @param $status
*/
protected function set_status( $status ) {
$this->status = $status;
}
/**
* Add data item.
*
* @param $item
*/
protected function add_data_item( $item ) {
$this->data[] = $item;
}
/**
* Add an error message.
*
* @param $error_message
*/
protected function add_error( $error_message ) {
$this->errors[] = $error_message;
}
/**
* Add a meta item to the response.
*
* @param $key
* @param $value
*/
protected function add_meta_item( $key, $value ) {
$this->meta[ $key ] = $value;
}
/**
* Get the data for this response
*
* @return array
*/
public function get_data() {
return $this->data;
}
/**
* Get any errors on this response.
*
* @return array
*/
public function get_errors() {
return $this->errors;
}
/**
* Get the response status.
*
* @return array
*/
public function get_status() {
return $this->status;
}
/**
* Get the response meta.
*
* @return array
*/
public function get_meta() {
return $this->meta;
}
/**
* Determine if the response has any errors.
*
* @return bool
*/
public function has_errors() {
return ! empty( $this->errors );
}
/**
* Get a specific piece of the data.
*
* @param $name
* @param int $index
*
* @return mixed|null
*/
public function get_data_value( $name, $index = 0 ) {
if ( ! isset( $this->data[ $index ][ $name ] ) ) {
return null;
}
return $this->data[ $index ][ $name ];
}
/**
* Standardization of the class when serialized and unserialized. Useful for standardizing how it
* is stored in the Database.
*
* @return string
*/
public function serialize() {
return serialize( $this->__serialize() );
}
/**
* Prepares the object for serializing.
*
* @since 2.6.2
*
* @return array
*/
public function __serialize() {
return array(
'data' => $this->data,
'errors' => $this->errors,
'status' => $this->status,
'meta' => $this->meta,
);
}
/**
* Hydrate the Response data when unserializing.
*
* @param string $serialized
*/
public function unserialize( $serialized ) {
$this->__unserialize( unserialize( $serialized ) );
}
/**
* Hydrates the object when unserializing.
*
* @since 2.6.2
*
* @param array $data The unserialized data.
*
* @return void
*/
public function __unserialize( $data ) {
$this->data = $data['data'];
$this->errors = $data['errors'];
$this->status = $data['status'];
$this->meta = $data['meta'];
}
/**
* Process data for JSON Encoding.
*
* @return array
*/
#[\ReturnTypeWillChange]
public function jsonSerialize() {
$response = array();
$response['status'] = $this->status;
$response['meta'] = $this->meta;
if ( empty( $this->errors ) ) {
$response['data'] = $this->data;
}
if ( ! empty( $this->errors ) ) {
$response['errors'] = $this->errors;
}
return $response;
}
}

View File

@@ -1,25 +0,0 @@
<?php
namespace Gravity_Forms\Gravity_Forms\External_API;
use Gravity_Forms\Gravity_Forms\External_API\GF_API_Response;
/**
* Interface GF_API_Response_Factory
*
* Contract to define how Response Factories should behave.
*
* @since 2.5
*
* @package Gravity_Forms\Gravity_Forms\External_API
*/
interface GF_API_Response_Factory {
/**
* @param mixed ...$args
*
* @return GF_API_Response
*/
public function create( ...$args );
}

View File

@@ -1,177 +0,0 @@
<?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' );
}
}
/**
* Get the field inputs.
*
* @since unknown
* @since 2.5 Add accessibility enhancements.
*
* @param array $form The form object.
* @param string $value The field value.
* @param array $entry The entry object.
*
* @return string
*/
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_legacy_markup = GFCommon::is_legacy_markup_enabled( $form );
$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"' : '';
$product_quantity_sub_label = $this->get_product_quantity_label( $form_id );
if ( $is_entry_detail || $is_form_editor ) {
$style = $this->disableQuantity ? "style='display:none;'" : '';
$quantity_field = " <span class='ginput_quantity_label gform-field-label gform-field-label--type-sub-large' {$style}>{$product_quantity_sub_label}</span> <input type='number' name='input_{$id}.3' value='{$quantity}' id='ginput_quantity_{$form_id}_{$this->id}' class='ginput_quantity' size='10' min='0' {$disabled_text} />";
} elseif ( ! $this->disableQuantity ) {
$tabindex = $this->get_tabindex();
$describedby_extra_id = array();
if ( ! $is_legacy_markup ) {
$describedby_extra_id = array( "ginput_product_price_{$this->formId}_{$this->id}" );
}
$quantity_aria_describedby = $this->get_aria_describedby( $describedby_extra_id );
$quantity_field .= " <span class='ginput_quantity_label gform-field-label' aria-hidden='true'>" . $product_quantity_sub_label . "</span> <input type='number' name='input_{$id}.3' value='{$quantity}' id='input_{$form_id}_{$this->id}_1' class='ginput_quantity' size='10' min='0' {$tabindex} {$disabled_text} {$quantity_aria_describedby} />";
} 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' />";
}
}
$wrapper_open = $is_legacy_markup ? '' : "<div id='ginput_product_price_{$form_id}_{$this->id}' class='ginput_product_price_wrapper'>";
$wrapper_close = $is_legacy_markup ? '' : '</div>';
return "<div class='ginput_container ginput_container_product_calculation'>
<input type='hidden' name='input_{$id}.1' value='{$product_name}' class='gform_hidden' />
$wrapper_open
<span class='gform-field-label gform-field-label--type-sub-large ginput_product_price_label'>" . gf_apply_filters( array( 'gform_product_price', $form_id, $this->id ), esc_html__( 'Price', 'gravityforms' ), $form_id ) . ":</span>
<span class='gform-field-label gform-field-label--type-sub-large ginput_product_price' id='{$field_id}'>" . esc_html( GFCommon::to_money( $price, $currency ) ) . "</span>
$wrapper_close
<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>";
}
/**
* Retrieve the field label.
*
* @since 2.5
*
* @param bool $force_frontend_label Should the frontend label be displayed in the admin even if an admin label is configured.
* @param string $value The field value. From default/dynamic population, $_POST, or a resumed incomplete submission.
*
* @return string
*/
public function get_field_label( $force_frontend_label, $value ) {
$field_label = parent::get_field_label( $force_frontend_label, $value );
// Checking the defined product name.
if ( ! rgempty( $this->id . '.1', $value ) ) {
$field_label = rgar( $value, $this->id . '.1' );
}
if ( $this->disableQuantity || ! $this->get_context_property( 'rendering_form' ) ) {
$label = esc_html( $field_label );
} else {
$product_quantity_sub_label = $this->get_product_quantity_label( $this->formId );
$label = '<span class="gfield_label_product gform-field-label">' . esc_html( $field_label ) . '</span>' . ' <span class="screen-reader-text">' . $product_quantity_sub_label . '</span>';
}
return $label;
}
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() );

View File

@@ -1,682 +0,0 @@
<?php
if ( ! class_exists( 'GFForms' ) ) {
die();
}
class GF_Field_CAPTCHA extends GF_Field {
/**
* @var string
*/
public $type = 'captcha';
/**
* The reCAPTCHA API response.
*
* @var \stdClass
*/
private $response;
/**
* The reCAPTCHA site key.
*
* @var string
*/
private $site_key;
/**
* The reCAPTCHA secret key.
*
* @var string
*/
private $secret_key;
public function get_form_editor_field_title() {
return esc_attr__( 'CAPTCHA', 'gravityforms' );
}
/**
* Returns the field's form editor description.
*
* @since 2.5
*
* @return string
*/
public function get_form_editor_field_description() {
return esc_attr__( 'Adds a captcha field to your form to help protect your website from spam and bot abuse.', 'gravityforms' );
}
/**
* Returns the field's form editor icon.
*
* This could be an icon url or a gform-icon class.
*
* @since 2.5
*
* @return string
*/
public function get_form_editor_field_icon() {
return 'gform-icon--recaptcha';
}
function get_form_editor_field_settings() {
return array(
'captcha_type_setting',
'captcha_badge_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',
);
}
/**
* Returns the warning message to be displayed in the form editor sidebar.
*
* @since 2.8
*
* @return string
*/
public function get_field_sidebar_messages() {
if ( $this->captchaType === 'math' || $this->captchaType === 'simple_captcha' || ( ! empty( $this->get_site_key() ) && ! empty( $this->get_secret_key() ) ) ) {
return '';
}
// Translators: 1. Opening <a> tag with link to the Forms > Settings > reCAPTCHA page. 2. closing <a> tag.
return sprintf( __( 'To use reCAPTCHA v2 you must configure the site and secret keys on the %1$sreCAPTCHA Settings%2$s page.', 'gravityforms' ), "<a href='?page=gf_settings&subview=recaptcha' target='_blank'>", '</a>' );
}
/**
* Validate the reCAPTCHA field.
*
* This method always gets called on the last page of a form, as well as on the page where the field is assigned.
*
* @since Unknown
*
* @param array|string $value The field value.
* @param array $form The form data.
*/
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->set_failed_validation( esc_html__( "The CAPTCHA wasn't entered correctly. Go back and try it again.", 'gravityforms' ) );
}
//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->set_failed_validation( esc_html__( "The CAPTCHA wasn't entered correctly. Go back and try it again.", 'gravityforms' ) );
}
//removes old files in captcha folder (older than 1 hour);
$captcha_obj->cleanup();
break;
default:
$this->validate_recaptcha( $form );
}
}
/**
* Validates the reCAPTCHA response.
*
* In our application flow, we create a decoded string out of the reCAPTCHA service response if the reCAPTCHA field
* is added to the form on a page other than the last page. We therefore first attempt to validate the decoded response,
* falling back to validating the reCAPTCHA with a request to Google.
*
* @see GF_Field_CAPTCHA::verify_decoded_response()
*
* @since unknown
*
* @param array $form The form data.
*
* @return bool
*/
public function validate_recaptcha( $form ) {
$response = $this->get_posted_recaptcha_response();
if ( ! ( $this->verify_decoded_response( $form, $response ) || $this->verify_recaptcha_response( $response ) ) ) {
$this->set_failed_validation( __( 'The reCAPTCHA was invalid. Go back and try it again.', 'gravityforms' ) );
return false;
}
return true;
}
/**
* Verifies that the decoded response meets the requirements for submitting the form.
*
* Returns false if the decoded response doesn't exist or the reCAPTCHA field is on the last page, as we'll want
* regular validation at that point instead.
*
* @since 2.4.24
*
* @param array $form The form data.
* @param string $response The encoded response to verify.
*
* @return bool
*/
private function verify_decoded_response( $form, $response ) {
$decoded_response = $this->get_decoded_recaptcha_response( $response );
// No decoded object.
if ( ! is_object( $decoded_response ) ) {
return false;
}
// Not a time that we need to verify the decoded object.
if ( ! GFFormDisplay::is_last_page( $form ) || $this->is_on_last_page( $form ) ) {
return false;
}
return (
$decoded_response->success === true
&& ! empty( $decoded_response->token )
&& gmdate( time() ) <= strtotime( '+1 day', strtotime( $decoded_response->challenge_ts ) )
);
}
/**
* Set validation failed on reCAPTCHA field.
*
* @since 2.4.24
*
* @param string $message The message to set if one does not already exist.
*/
private function set_failed_validation( $message ) {
$this->failed_validation = true;
$this->validation_message = empty( $this->errorMessage ) ? $message : $this->errorMessage;
}
/**
* Get the saved site key.
*
* @since 2.4.24
*
* @return string
*/
public function get_site_key() {
if ( ! $this->site_key ) {
$this->site_key = get_option( 'rg_gforms_captcha_public_key', '' );
}
return $this->site_key;
}
/**
* Get the saved secret key.
*
* @since 2.4.25
*
* @return string
*/
public function get_secret_key() {
if ( ! $this->secret_key ) {
$this->secret_key = get_option( 'rg_gforms_captcha_private_key', '' );
}
return $this->secret_key;
}
/**
* Get the value of the reCAPTCHA response input.
*
* When user clicks on the "I'm not a robot" box, the response token is populated into a hidden field by Google.
* If the current form is a multi-page form and the reCAPTCHA field is on a page other than the last page, this
* value will return an openssl encoded string with the Google reCAPTCHA validation data and some supplemental
* validation data instead.
*
* @see GF_Field_CAPTCHA::get_encoded_recaptcha_response()
*
* @since 2.4.24
*
* @return string
*/
private function get_posted_recaptcha_response() {
return sanitize_text_field( rgpost( 'g-recaptcha-response' ) );
}
/**
* Validate the reCAPTCHA token provided by Google.
*
* @since unknown
*
* @param string $response The token to verify.
* @param null $secret_key The secret key for reCAPTCHA verification.
*
* @return bool
*/
public function verify_recaptcha_response( $response, $secret_key = null ) {
$verify_url = 'https://www.google.com/recaptcha/api/siteverify';
if ( $secret_key == null ) {
$secret_key = $this->get_secret_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 ) ) {
$this->response = json_decode( wp_remote_retrieve_body( $response ) );
return $this->response->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' autocomplete='off' 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' autocomplete='off' name='input_{$id}' id='{$field_id}' {$tabindex}/><input type='hidden' name='input_captcha_prefix_{$id}' value='" . esc_attr( $prefix_value ) . "' /></div></div>";
break;
default:
$this->site_key = $this->get_site_key();
$this->secret_key = $this->get_secret_key();
$theme = in_array( $this->captchaTheme, array( 'blackglass', 'dark' ) ) ? 'dark' : 'light';
$type = get_option( 'rg_gforms_captcha_type' );
if ( $is_entry_detail || $is_form_editor ){
//for admin, show a thumbnail depending on chosen theme
if ( empty( $this->site_key ) || empty( $this->secret_key ) ) {
return "<div class='ginput_container'><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 %sreCAPTCHA Settings%s.', 'gravityforms' ), "<a href='?page=gf_settings&subview=recaptcha' target='_blank'>", '</a>' ) . '</div></div>';
}
$type_suffix = $type == 'invisible' ? 'invisible_' : '';
$alt = esc_attr__( 'An example of reCAPTCHA', 'gravityforms' );
return "<div class='ginput_container'><img class='gfield_captcha' src='" . GFCommon::get_base_url() . "/images/captcha_{$type_suffix}{$theme}.jpg' alt='{$alt}' /></div>";
}
if ( empty( $this->site_key ) || empty( $this->secret_key ) ) {
GFCommon::log_error( __METHOD__ . sprintf( '(): reCAPTCHA secret keys not saved in the reCAPTCHA Settings (%s). The reCAPTCHA field will always fail validation during form submission.', admin_url( 'admin.php' ) . '?page=gf_settings&subview=recaptcha' ) );
}
$stoken = '';
if ( ! empty( $this->secret_key ) && ! empty( $secure_token ) && $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( $this->secret_key );
$stoken = sprintf( 'data-stoken=\'%s\'', esc_attr( $secure_token ) );
}
$size = '';
$badge = '';
if ( $type == 'invisible' ) {
$size = "data-size='invisible'";
$badge = $this->captchaBadge ? $this->captchaBadge : 'bottomright';
$tabindex = -1;
} else {
$tabindex = GFCommon::$tab_index > 0 ? GFCommon::$tab_index++ : 0;
}
$output = "<div id='" . esc_attr( $field_id ) ."' class='ginput_container ginput_recaptcha' data-sitekey='" . esc_attr( $this->site_key ) . "' {$stoken} data-theme='" . esc_attr( $theme ) . "' data-tabindex='{$tabindex}' {$size} data-badge='{$badge}'></div>";
$recaptcha_response = $this->get_posted_recaptcha_response();
if ( ! $this->requires_encoding( $form, $recaptcha_response ) ) {
return $output;
}
ob_start();
?>
<input
type="hidden"
name="g-recaptcha-response"
value="<?php esc_attr_e( $this->get_encoded_recaptcha_response( $form, $recaptcha_response) ); ?>"
/>
<?php
return $output .= ob_get_clean();
}
}
/**
* Encode the reCAPTCHA response with details from Google.
*
* @since 2.4.24
*
* @param array $form The form data.
* @param string $response The posted response data.
*
* @return string
*/
private function get_encoded_recaptcha_response( $form, $response ) {
if ( ! $this->response ) {
return $response;
}
$this->response->token = $response;
return GFCommon::openssl_encrypt( base64_encode( json_encode( $this->response ) ), $this->secret_key );
}
/**
* Decode and return the value of g-recaptcha-response field.
*
* The first time this method is called, the $response parameter will be the result of the reCAPTCHA callback,
* and decryption will fail. On subsequent requests, it should contain an encoded string of the reCAPTCHA response
* and the original token used to make the request.
*
* @since 2.4.24
*
* @param string $response An openssl encoded string, or the reCAPTCHA token on the very first call.
*
* @return string
*/
private function get_decoded_recaptcha_response( $response ) {
$decoded_response = GFCommon::openssl_decrypt( $response, $this->get_secret_key() );
if ( ! $decoded_response ) {
return;
}
return json_decode( base64_decode( $decoded_response ) );
}
/**
* Check whether the reCAPTCHA response should be saved and encoded for validation on the final form page.
*
* @since 2.4.24
*
* @param array $form The form data.
* @param string $recaptcha_response The reCAPTCHA response.
*
* @return bool
*/
private function requires_encoding( $form, $recaptcha_response ) {
return $recaptcha_response && ! $this->failed_validation && GFFormDisplay::get_current_page( rgar( $form, 'id' ) ) != $this->pageNumber && ! $this->is_on_last_page( $form );
}
/**
* Returns true if this CAPTCHA field is on the last page of the given form.
*
* @since 2.4.24
*
* @param array $form The form data.
*
* @return bool
*/
private function is_on_last_page( $form ) {
$pages = GFAPI::get_fields_by_type( $form, array( 'page' ) );
return count( $pages ) + 1 === (int) $this->pageNumber;
}
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 ) {
// If required cypher is not available, skip
if ( ! defined( 'MCRYPT_RIJNDAEL_128' ) ) {
GFCommon::log_error( __METHOD__ . sprintf( '(): Legacy MCRYPT_RIJNDAEL_128 cypher not available on system. Generate new reCAPTCHA v2 keys (https://www.google.com/recaptcha/admin/create) and update your Gravity Forms reCAPTCHA Settings (%s) to resolve.', admin_url( 'admin.php' ) . '?page=gf_settings&subview=recaptcha' ) );
return '';
}
$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
$encrypted = GFCommon::openssl_encrypt( $padded, $secret_key, MCRYPT_RIJNDAEL_128 );
$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() );

View File

@@ -1,596 +0,0 @@
<?php
if ( ! class_exists( 'GFForms' ) ) {
die();
}
/**
* The Consent Field keeps track of exactly what the user consented to. The consent value ("1"), checkbox label and the Form revision ID
* are all stored in the entry meta table in separate input values when consent is given.
*
* @since 2.4
*
* Class GF_Field_Consent
*/
class GF_Field_Consent extends GF_Field {
/**
* Declare the field type.
*
* @since 2.4
*
* @var string
*/
public $type = 'consent';
/**
* Checked indicator URL.
*
* @since 2.4
*
* @var string
*/
public $checked_indicator_url = '';
/**
* Checked indicator image markup.
*
* @since 2.4
*
* @var string
*/
public $checked_indicator_markup = '';
/**
* Indicates if this field supports state validation.
*
* @since 2.5.11
*
* @var bool
*/
protected $_supports_state_validation = true;
/**
* GF_Field_Consent constructor.
*
* @since 2.4
*
* @param array $data Data needed when initiate the class.
*/
public function __construct( $data = array() ) {
parent::__construct( $data );
/**
* Filters the consent checked indicator (image) URL.
*
* @since 2.4
*
* @param string $url Image URL.
*/
$this->checked_indicator_url = apply_filters( 'gform_consent_checked_indicator', GFCommon::get_base_url() . '/images/tick.png' );
/**
* Filters the consent checked indicator (image) element.
*
* @since 2.4
*
* @param string $tag Image tag.
*/
$this->checked_indicator_markup = apply_filters( 'gform_consent_checked_indicator_markup', '<img src="' . esc_url( $this->checked_indicator_url ) . '" />' );
}
/**
* Returns the field title.
*
* @since 2.4
*
* @return string
*/
public function get_form_editor_field_title() {
return esc_attr__( 'Consent', 'gravityforms' );
}
/**
* Returns the field's form editor description.
*
* @since 2.5
*
* @return string
*/
public function get_form_editor_field_description() {
return esc_attr__( 'Offers a “yes/no” consent checkbox and a detailed description of what is being consented to.', 'gravityforms' );
}
/**
* Returns the field's form editor icon.
*
* This could be an icon url or a gform-icon class.
*
* @since 2.5
*
* @return string
*/
public function get_form_editor_field_icon() {
return 'gform-icon--consent';
}
/**
* Returns the field button properties for the form editor. The array contains two elements:
* 'group' => 'standard_fields' // or 'advanced_fields', 'post_fields', 'pricing_fields'
* 'text' => 'Button text'
*
* @since 2.4
*
* @return array
*/
public function get_form_editor_button() {
return array(
'group' => 'advanced_fields',
'text' => $this->get_form_editor_field_title(),
);
}
/**
* Returns the class names of the settings which should be available on the field in the form editor.
*
* @since 2.4
*
* @return array
*/
public function get_form_editor_field_settings() {
return array(
'conditional_logic_field_setting',
'error_message_setting',
'label_setting',
'label_placement_setting',
'admin_label_setting',
'checkbox_label_setting',
'rules_setting',
'visibility_setting',
'description_setting',
'css_class_setting',
);
}
/**
* Indicate if this field type can be used when configuring conditional logic rules.
*
* @since 2.4
*
* @return bool
*/
public function is_conditional_logic_supported() {
return true;
}
/**
* Returns the HTML tag for the field container.
*
* @since 2.5
*
* @param array $form The current Form object.
*
* @return string
*/
public function get_field_container_tag( $form ) {
if ( GFCommon::is_legacy_markup_enabled( $form ) ) {
return parent::get_field_container_tag( $form );
}
return 'fieldset';
}
/**
* Returns the field inner markup.
*
* @since 2.4
*
* @param array $form The Form Object currently being processed.
* @param 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
*/
public function get_field_input( $form, $value = array(), $entry = null ) {
$is_entry_detail = $this->is_entry_detail();
$is_form_editor = $this->is_form_editor();
$is_admin = $is_form_editor || $is_entry_detail;
$html_input_type = 'checkbox';
$id = (int) $this->id;
$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"';
$target_input_id = parent::get_first_input_id( $form );
$for_attribute = empty( $target_input_id ) ? '' : "for='{$target_input_id}'";
$label_class_attribute = 'class="gform-field-label gform-field-label--type-inline gfield_consent_label"';
$required_div = ( $this->labelPlacement === 'hidden_label' && $this->isRequired ) ? $this->get_required_indicator() : '';
if ( $is_admin && ! GFCommon::is_entry_detail_edit() ) {
$checkbox_label = ! is_array( $value ) || empty( $value[ $id . '.2' ] ) ? $this->checkboxLabel : $value[ $id . '.2' ];
$revision_id = ! is_array( $value ) || empty( $value[ $id . '.3' ] ) ? GFFormsModel::get_latest_form_revisions_id( $form['id'] ) : $value[ $id . '.3' ];
$value = ! is_array( $value ) || empty( $value[ $id . '.1' ] ) ? '0' : esc_attr( $value[ $id . '.1' ] );
} else {
$checkbox_label = trim( $this->checkboxLabel );
$revision_id = GFFormsModel::get_latest_form_revisions_id( $form['id'] );
// We compare if the description text from different revisions has been changed.
$current_description = $this->get_field_description_from_revision( $revision_id );
$submitted_description = $this->get_field_description_from_revision( $value[ $id . '.3' ] );
$value = ! is_array( $value ) || empty( $value[ $id . '.1' ] ) || ( $checkbox_label !== $value[ $id . '.2' ] ) || ( $current_description !== $submitted_description ) ? '0' : esc_attr( $value[ $id . '.1' ] );
}
$checked = $is_form_editor ? '' : checked( '1', $value, false );
$description = $is_entry_detail ? $this->get_field_description_from_revision( $revision_id ) : $this->description;
$extra_describedby_ids = empty( $description ) ? array() : array( "gfield_consent_description_{$form['id']}_{$this->id}" );
$aria_describedby = $this->get_aria_describedby( $extra_describedby_ids );
$input = "<input name='input_{$id}.1' id='{$target_input_id}' type='{$html_input_type}' value='1' {$tabindex} {$aria_describedby} {$required_attribute} {$invalid_attribute} {$disabled_text} {$checked} /> <label {$label_class_attribute} {$for_attribute} >{$checkbox_label}{$required_div}</label>";
$input .= "<input type='hidden' name='input_{$id}.2' value='" . esc_attr( $checkbox_label ) . "' class='gform_hidden' />";
$input .= "<input type='hidden' name='input_{$id}.3' value='" . esc_attr( $revision_id ) . "' class='gform_hidden' />";
if ( $is_entry_detail ) {
$input .= $this->get_description( $this->get_field_description_from_revision( $revision_id ), '' );
}
return sprintf( "<div class='ginput_container ginput_container_consent'>%s</div>", $input );
}
/**
* Returns the input ID to be assigned to the field label for attribute.
*
* @since 2.4
*
* @param array $form The Form Object currently being processed.
*
* @return string
*/
public function get_first_input_id( $form ) {
return '';
}
/**
* Returns the markup for the field description.
*
* @since 2.4
*
* @param string $description The field description.
* @param string $css_class The css class to be assigned to the description container.
*
* @return string
*/
public function get_description( $description, $css_class ) {
if ( ! empty( $description ) ) {
$id = "gfield_consent_description_{$this->formId}_{$this->id}";
$css_class .= ' gfield_consent_description';
return "<div class='$css_class' id='$id'>" . nl2br( $description ) . '</div>';
}
return parent::get_description( $description, $css_class );
}
/**
* If a field has a description, the aria-describedby attribute for the input field is returned.
* This method is specific to the consent field since the consent description has a different ID pattern.
*
* @since 2.6.8
*
* @param array|string $extra_ids Any extra ids that should be added to the describedby attribute.
*
* @return string
*/
public function get_aria_describedby( $extra_ids = array() ) {
$describedby_ids = is_array( $extra_ids ) ? $extra_ids : explode( ' ', $extra_ids );
if ( $this->failed_validation ) {
$describedby_ids[] = "validation_message_{$this->formId}_{$this->id}";
}
if ( empty( $describedby_ids ) ) {
return '';
}
return 'aria-describedby="' . implode( ' ', $describedby_ids ) . '"';
}
/**
* Used when determining if the field has failed required validation.
*
* The consent field has three inputs; only the checkbox is required.
*
* @since 2.7.5
*
* @param int $form_id The ID of the form currently being processed.
*
* @return bool
*/
public function is_value_submission_empty( $form_id ) {
return rgblank( rgpost( 'input_' . $this->id . '_1' ) );
}
/**
* Sanitize and format the value before it is saved to the Entry Object.
* We also add the value of inputs .2 and .3 here since they are not displayed in the form.
*
* @since 2.4
*
* @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.
*
* @return array|string The safe value.
*/
public function get_value_save_entry( $value, $form, $input_name, $lead_id, $lead ) {
list( $input, $field_id, $input_id ) = rgexplode( '_', $input_name, 3 );
switch ( $input_id ) {
case '1':
$value = ( ! empty( $value ) ) ? '1' : '';
break;
case '2':
$value = ( $lead[ $field_id . '.1' ] === '1' ) ? $value : '';
break;
case '3':
$value = ( $lead[ $field_id . '.1' ] === '1' ) ? $value : '';
break;
}
return $value;
}
/**
* Set the values of consent field inputs in merge tags.
*
* @since 2.4
*
* @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 ) {
list( $field_id, $input_id ) = explode( '.', $input_id );
switch ( $input_id ) {
case '1':
$value = ! rgblank( $value ) ? $this->checked_indicator_markup : '';
break;
case '3':
$value = ! rgblank( $value ) ? $this->get_field_description_from_revision( $value ) : '';
if ( $value !== '' && $nl2br ) {
$value = nl2br( $value );
}
break;
}
return $value;
}
/**
* Format the entry value for display on the entries list page.
*
* @since 2.4
*
* @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
*/
public function get_value_entry_list( $value, $entry, $field_id, $columns, $form ) {
list( $field_id, $input_id ) = explode( '.', $field_id );
switch ( $input_id ) {
case '1':
$value = ! rgblank( $value ) ? $this->checked_indicator_markup : '';
$value .= ! rgblank( $value ) ? ' ' . trim( $entry[ $this->id . '.2' ] ) : '';
break;
}
return $value;
}
/**
* Format the entry value for display on the entry detail page and for the {all_fields} merge tag.
*
* @since 2.4
*
* @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' ) {
$return = '';
if ( is_array( $value ) && ! empty( $value ) ) {
$consent = trim( $value[ $this->id . '.1' ] );
$text = trim( $value[ $this->id . '.2' ] );
$revision_id = absint( trim( $value[ $this->id . '.3' ] ) );
if ( ! rgblank( $consent ) ) {
$return = $this->checked_indicator_markup;
$return .= ' ' . wp_kses_post( $text );
if ( $media === 'screen' ) {
// checking revisions.
$description = $this->get_field_description_from_revision( $revision_id );
if ( ! empty( $description ) ) {
$return .= '<br /><div class="gfield_consent_description">' . nl2br( $description ) . '</div>';
}
}
}
}
return $return;
}
/**
* Format the entry value before it is used in entry exports and by framework add-ons using GFAddOn::get_field_value().
*
* For CSV export return a string or array.
*
* @since 2.4
*
* @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|array
*/
public function get_value_export( $entry, $input_id = '', $use_text = false, $is_csv = false ) {
if ( empty( $input_id ) ) {
return '';
}
$value = parent::get_value_export( $entry, $input_id, $use_text, $is_csv );
list( $field_id, $input_id ) = rgexplode( '.', $input_id, 2 );
switch ( $input_id ) {
case '1':
$value = ! rgblank( $value ) ? esc_html__( 'Checked', 'gravityforms' ) : esc_html__( 'Not Checked', 'gravityforms' );
break;
case '3':
$value = ! rgblank( $value ) ? $this->get_field_description_from_revision( $value ) : '';
break;
}
return $value;
}
/**
* Forces settings into expected values while saving the form object.
*
* No escaping should be done at this stage to prevent double escaping on output.
*
* @since 2.4
*/
public function sanitize_settings() {
parent::sanitize_settings();
$this->checkboxLabel = $this->maybe_wp_kses( $this->checkboxLabel );
}
/**
* Returns the filter settings for the current field.
*
* If overriding to add custom settings call the parent method first to get the default settings.
*
* @since 2.4
*
* @return array
*/
public function get_filter_settings() {
$filter_settings = array(
'key' => $this->id . '.1',
'text' => GFFormsModel::get_label( $this ),
'preventMultiple' => false,
'operators' => $this->get_filter_operators(),
);
$values = $this->get_filter_values();
if ( ! empty( $values ) ) {
$filter_settings['values'] = $values;
}
return $filter_settings;
}
/**
* Returns the filter operators for the current field.
*
* @since 2.4
*
* @return array
*/
public function get_filter_operators() {
$operators = array( 'is', 'isnot' );
return $operators;
}
/**
* Returns the filters values setting for the current field.
*
* @since 2.4
*
* @return array
*/
public function get_filter_values() {
$choices = array(
array(
'value' => '1',
'text' => esc_html__( 'Checked', 'gravityforms' ),
),
);
return $choices;
}
/**
* Get consent description from the form revision.
*
* @since 2.4
*
* @param int $revision_id Revision ID.
*
* @return string
*/
public function get_field_description_from_revision( $revision_id ) {
global $wpdb;
$revisions_table_name = GFFormsModel::get_form_revisions_table_name();
$display_meta = $wpdb->get_var( $wpdb->prepare( "SELECT display_meta FROM $revisions_table_name WHERE form_id=%d AND id=%d", $this->formId, $revision_id ) );
$value = '';
$is_entry_detail = $this->is_entry_detail();
if ( ! empty( $display_meta ) ) {
$display_meta_array = json_decode( $display_meta, true );
foreach ( $display_meta_array['fields'] as $field ) {
if ( $field['id'] === $this->id ) {
$value = $field['description'];
break;
}
}
} else {
$value = ( ! empty( $this->description ) ) ? $this->description : '';
}
if ( $is_entry_detail ) {
$value = $this->maybe_wp_kses( $value );
}
return $value;
}
}
GF_Fields::register( new GF_Field_Consent() );

View File

@@ -1,626 +0,0 @@
<?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' );
}
/**
* Returns the field's form editor description.
*
* @since 2.5
*
* @return string
*/
public function get_form_editor_field_description() {
return esc_attr__( 'Allows users to enter credit card information.', 'gravityforms' );
}
/**
* Returns the field's form editor icon.
*
* This could be an icon url or a gform-icon class.
*
* @since 2.5
*
* @return string
*/
public function get_form_editor_field_icon() {
return 'gform-icon--credit-card';
}
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
}
/**
* Defines the IDs of required inputs.
*
* @since 2.5
*
* @return string[]
*/
public function get_required_inputs_ids() {
return array( '1', '2_month', '2_year', '3' );
}
/**
* Generates an array that contains aria-describedby attribute for each input.
*
* Depending on each input's validation state, aria-describedby takes the value of the validation message container ID, the description only or nothing.
*
* @since 2.5
*
* @param array $required_inputs_ids IDs of required field inputs.
* @param array|string $values Inputs values.
*
* @return array
*/
public function get_inputs_describedby_attributes( $required_inputs_ids, $values ) {
$describedby_attributes = array();
$warning_container_id = ! GFCommon::is_ssl() && ! ( $this->is_form_editor() || $this->is_entry_detail() ) ? "field_{$this->formId}_{$this->id}_creditcard_warning_message" : '';
foreach ( $this->inputs as $input ) {
$input_id = str_replace( $this->id . '.', '', $input['id'] );
$input_value = GFForms::get( $input['id'], $values );
if ( ! empty( $_POST[ 'is_submit_' . $this->formId ] ) && $this->isRequired && in_array( $input_id, $required_inputs_ids ) && empty( $input_value ) ) {
$describedby_attributes[ $input_id ] = "aria-describedby='validation_message_{$this->formId}_{$this->id} {$warning_container_id}'";
} else {
$describedby_attributes[ $input_id ] = empty( $warning_container_id ) ? '' : "aria-describedby='{$warning_container_id}'";
}
}
return $describedby_attributes;
}
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;
}
/**
* Returns the HTML tag for the field container.
*
* @since 2.5
*
* @param array $form The current Form object.
*
* @return string
*/
public function get_field_container_tag( $form ) {
if ( GFCommon::is_legacy_markup_enabled( $form ) ) {
return parent::get_field_container_tag( $form );
}
return 'fieldset';
}
/**
* Displays an insecure page warning below the field content.
*
* @since 2.5
*
* @param string|array $value The field value. From default/dynamic population, $_POST, or a resumed incomplete submission.
* @param bool $force_frontend_label Should the frontend label be displayed in the admin even if an admin label is configured.
* @param array $form The Form Object currently being processed.
*
* @return string
*/
public function get_field_content( $value, $force_frontend_label, $form ) {
$is_form_editor = GFCommon::is_form_editor();
$is_entry_detail = GFCommon::is_entry_detail();
$is_admin = $is_form_editor || $is_entry_detail;
// Get existing field content.
$field_content = parent::get_field_content( $value, $force_frontend_label, $form );
// If SSL is not used, display warning message.
if ( ! GFCommon::is_ssl() && ! $is_admin ) {
$field_content = "<div class='gfield_description gfield_validation_message gfield_creditcard_warning_message' id='field_{$form['id']}_{$this->id}_creditcard_warning_message'><span>" . esc_html__( 'This page is unsecured. Do not enter a real credit card number! Use this field only for testing purposes. ', 'gravityforms' ) . '</span></div>' . $field_content;
}
return $field_content;
}
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 = $field_sub_label_placement == 'hidden_label' ? "hidden_sub_label screen-reader-text" : '';
$card_number = '';
$card_name = '';
$expiration_month = '';
$expiration_year = '';
$security_code = '';
$autocomplete = "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();
$enabled_card_names = array();
foreach ( $cards as $card ) {
$style = '';
if ( $this->is_card_supported( $card['slug'] ) ) {
$print_card = true;
$enabled_card_names[] = rgar( $card, 'name' );
} 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_describer = sprintf(
"<span class='screen-reader-text' id='field_%d_%d_supported_creditcards'>%s %s</span>",
$form_id,
$this->id,
esc_html__( 'Supported Credit Cards:', 'gravityforms' ),
implode( ', ', $enabled_card_names )
);
$card_icons = "{$payment_options}<div class='gform_card_icon_container'>{$card_radio_button}{$card_icons}{$card_describer}</div>";
// Aria attributes.
$number_aria_attributes = $this->get_aria_attributes( $value, '1' );
$expiration_month_aria_attributes = $this->get_aria_attributes( $value, '2_month' );
$expiration_year_aria_attributes = $this->get_aria_attributes( $value, '2_year' );
$security_aria_attributes = $this->get_aria_attributes( $value, '3' );
$name_aria_attributes = $this->get_aria_attributes( $value, '5' );
//card number fields
$tabindex = $this->get_tabindex();
$card_number_field_input = GFFormsModel::get_input( $this, $this->id . '.1' );
$validation_helper = ! is_admin() ? "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} gform-grid-col' id='{$field_id}_1_container' >
{$card_icons}
<label for='{$field_id}_1' id='{$field_id}_1_label' class='gform-field-label gform-field-label--type-sub {$sub_label_class}'>{$card_number_label}</label>
<input type='text' name='input_{$id}.1' id='{$field_id}_1' value='{$card_number}' {$tabindex} {$disabled_text} {$onchange} {$onkeyup} {$autocomplete} {$validation_helper} {$card_number_placeholder} {$number_aria_attributes}/>
</span>";
} else {
$card_field = "<span class='ginput_full{$class_suffix} gform-grid-col' 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} {$validation_helper} {$card_number_placeholder} {$number_aria_attributes}/>
<label for='{$field_id}_1' id='{$field_id}_1_label' class='gform-field-label gform-field-label--type-sub {$sub_label_class}'>{$card_number_label}</label>
</span>";
}
// Expiration Date Inputs
$expiration_wrapper_tag = $this->get_field_container_tag( $form ) === 'fieldset' ? 'fieldset' : 'span';
$expiration_label_tag = $expiration_wrapper_tag === 'fieldset' ? 'legend' : 'label';
$expiration_label_for = $expiration_label_tag === 'label' ? " for='{$field_id}_2_month'" : '';
$expiration_month_input = GFFormsModel::get_input( $this, $this->id . '.2_month' );
$expiration_label = rgar( $expiration_month_input, 'customLabel' ) != '' ? esc_html( $expiration_month_input['customLabel'] ) : esc_html__( 'Expiration Date', 'gravityforms' );
$expiration_label = gf_apply_filters( array( 'gform_card_expiration', $form_id ), $expiration_label, $form_id );
// Expiration Date: Month
$expiration_month_label = $expiration_wrapper_tag === 'fieldset' ? "<label for='{$field_id}_2_month' class='gform-field-label gform-field-label--type-sub screen-reader-text'>" . esc_html__( 'Month', 'gravityforms' ) . "</label>" : '';
$expiration_month_tab_index = $this->get_tabindex();
$expiration_month_placeholder = $this->get_input_placeholder_value( $expiration_month_input );
$expiration_months = $this->get_expiration_months( $expiration_month, $expiration_month_placeholder );
// Expiration Date: Year
$expiration_year_input = GFFormsModel::get_input( $this, $this->id . '.2_year' );
$expiration_year_tab_index = $this->get_tabindex();
$expiration_year_placeholder = $this->get_input_placeholder_value( $expiration_year_input );
$expiration_years = $this->get_expiration_years( $expiration_year, $expiration_year_placeholder );
if ( $expiration_wrapper_tag === 'fieldset' ) {
$expiration_year_label_for = $is_form_editor ? '' : $field_id . '_2_year';
$expiration_year_label = "<label for='{$expiration_year_label_for}' class='gform-field-label gform-field-label--type-sub screen-reader-text'>" . esc_html__( 'Year', 'gravityforms' ) . "</label>";
} else {
$expiration_year_label = '';
}
// legend tag should be the first child of fieldset, so we are putting out this markup for fieldset
// even if the sub-label is below or hidden.
if ( $expiration_wrapper_tag === 'fieldset' || $is_sub_label_above ) {
$expiration_field = "<span class='ginput_full{$class_suffix} ginput_cardextras gform-grid-col gform-grid-row' id='{$field_id}_2_container'>
<{$expiration_wrapper_tag} class='ginput_cardinfo_left{$class_suffix} gform-grid-col' id='{$field_id}_2_cardinfo_left'>
<{$expiration_label_tag}{$expiration_label_for} class='gform-field-label gform-field-label--type-sub {$sub_label_class}'>{$expiration_label}</{$expiration_label_tag}>
<span class='ginput_card_expiration_container ginput_card_field gform-grid-row'>
" . ( $expiration_wrapper_tag === 'fieldset' ? "<span class='ginput_card_expiration_month_container gform-grid-col'>" : "" ) . "
{$expiration_month_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_month_aria_attributes}>
{$expiration_months}
</select>
" . ( $expiration_wrapper_tag === 'fieldset' ? "</span>" : "" ) . "
" . ( $expiration_wrapper_tag === 'fieldset' ? "<span class='ginput_card_expiration_year_container gform-grid-col'>" : "" ) . "
{$expiration_year_label}
<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_year_aria_attributes}>
{$expiration_years}
</select>
" . ( $expiration_wrapper_tag === 'fieldset' ? "</span>" : "" ) . "
</span>
</{$expiration_wrapper_tag}>";
} else {
$expiration_field = "<span class='ginput_full{$class_suffix} ginput_cardextras gform-grid-col gform-grid-row' id='{$field_id}_2_container'>
<{$expiration_wrapper_tag} class='ginput_cardinfo_left{$class_suffix}' id='{$field_id}_2_cardinfo_left'>
<span class='ginput_card_expiration_container ginput_card_field'>
" . ( $expiration_wrapper_tag === 'fieldset' ? "<span class='ginput_card_expiration_month_container'>" : "" ) . "
<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_month_aria_attributes}>
{$expiration_months}
</select>
{$expiration_month_label}
" . ( $expiration_wrapper_tag === 'fieldset' ? "</span>" : "" ) . "
" . ( $expiration_wrapper_tag === 'fieldset' ? "<span class='ginput_card_expiration_year_container'>" : "" ) . "
<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_year_aria_attributes}>
{$expiration_years}
</select>
{$expiration_year_label}
" . ( $expiration_wrapper_tag === 'fieldset' ? "</span>" : "" ) . "
</span>
<{$expiration_label_tag}{$expiration_label_for} class='gform-field-label gform-field-label--type-sub {$sub_label_class}'>{$expiration_label}</{$expiration_label_tag}>
</{$expiration_wrapper_tag}>";
}
//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 );
$validation_helper = "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} gform-grid-col' id='{$field_id}_2_cardinfo_right'>
<label for='{$field_id}_3' class='gform-field-label gform-field-label--type-sub {$sub_label_class}'>$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} {$validation_helper} {$security_code_placeholder} {$security_aria_attributes}/>
<span class='ginput_card_security_code_icon'>&nbsp;</span>
</span>
</span>";
} else {
$security_field = "<span class='ginput_cardinfo_right{$class_suffix} gform-grid-col' 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} {$validation_helper} {$security_code_placeholder} {$security_aria_attributes}/>
<span class='ginput_card_security_code_icon'>&nbsp;</span>
<label for='{$field_id}_3' class='gform-field-label gform-field-label--type-sub {$sub_label_class}'>$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} gform-grid-col' id='{$field_id}_5_container'>
<label for='{$field_id}_5' id='{$field_id}_5_label' class='gform-field-label gform-field-label--type-sub {$sub_label_class}'>{$card_name_label}</label>
<input type='text' name='input_{$id}.5' id='{$field_id}_5' value='{$card_name}' {$tabindex} {$disabled_text} {$card_name_placeholder} {$name_aria_attributes}/>
</span>";
} else {
$card_name_field = "<span class='ginput_full{$class_suffix} gform-grid-col' 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} {$name_aria_attributes}/>
<label for='{$field_id}_5' id='{$field_id}_5_label' class='gform-field-label gform-field-label--type-sub {$sub_label_class}'>{$card_name_label}</label>
</span>";
}
return "<div class='ginput_complex{$class_suffix} ginput_container ginput_container_creditcard gform-grid-row' id='{$field_id}'>" . $card_field . $expiration_field . $security_field . $card_name_field . ' </div>';
}
/**
* Get the options for the Expiration Date Month drop down.
*
* @since Unknown
* @since 2.5 Added $included_placeholder parameter.
*
* @param string $selected_month The currently selected month.
* @param string $placeholder Placeholder text.
*
* @return string
*/
private function get_expiration_months( $selected_month, $placeholder ) {
$str = '';
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;
}
/**
* Get the options for the Expiration Date Year drop down.
*
* @since Unknown
* @since 2.5 Added $included_placeholder parameter.
*
* @param string $selected_year The currently selected year.
* @param string $placeholder Placeholder text.
*
* @return string
*/
private function get_expiration_years( $selected_year, $placeholder ) {
$str = '';
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() );

Some files were not shown because too many files have changed in this diff Show More