Your Gravity Forms License Key has expired. In order to continue receiving support and software updates you must renew your license key. You can do so by following the renewal instructions on the Gravity Forms Settings page in your WordPress Dashboard or by clicking here.";
}
$from = rgempty( 'fromField', $form['notification'] ) ? rgget( 'from', $form['notification'] ) : rgget( $form['notification']['fromField'], $lead );
if ( rgempty( 'fromNameField', $form['notification'] ) ) {
$from_name = rgget( 'fromName', $form['notification'] );
} else {
$field = RGFormsModel::get_field( $form, rgget( 'fromNameField', $form['notification'] ) );
$value = RGFormsModel::get_lead_field_value( $lead, $field );
$from_name = GFCommon::get_lead_field_display( $field, $value );
}
$replyTo = rgempty( 'replyToField', $form['notification'] ) ? rgget( 'replyTo', $form['notification'] ) : rgget( $form['notification']['replyToField'], $lead );
if ( rgempty( 'routing', $form['notification'] ) ) {
$email_to = rgempty( 'toField', $form['notification'] ) ? rgget( 'to', $form['notification'] ) : rgget( 'toField', $form['notification'] );
} else {
$email_to = array();
foreach ( $form['notification']['routing'] as $routing ) {
$source_field = RGFormsModel::get_field( $form, $routing['fieldId'] );
$field_value = RGFormsModel::get_lead_field_value( $lead, $source_field );
$is_value_match = RGFormsModel::is_value_match( $field_value, $routing['value'], $routing['operator'], $source_field, $routing, $form ) && ! RGFormsModel::is_field_hidden( $form, $source_field, array(), $lead );
if ( $is_value_match ) {
$email_to[] = $routing['email'];
}
}
$email_to = join( ',', $email_to );
}
//Running through variable replacement
$email_to = GFCommon::replace_variables( $email_to, $form, $lead, false, false );
$from = GFCommon::replace_variables( $from, $form, $lead, false, false );
$bcc = GFCommon::replace_variables( rgget( 'bcc', $form['notification'] ), $form, $lead, false, false );
$reply_to = GFCommon::replace_variables( $replyTo, $form, $lead, false, false );
$from_name = GFCommon::replace_variables( $from_name, $form, $lead, false, false );
//Filters the admin notification email to address. Allows users to change email address before notification is sent
$to = gf_apply_filters( array( 'gform_notification_email', $form_id ), $email_to, $lead );
// override default values if override options provided
if ( $override_options && is_array( $override_options ) ) {
foreach ( $override_options as $override_key => $override_value ) {
${$override_key} = $override_value;
}
}
$attachments = gf_apply_filters( array(
'gform_admin_notification_attachments',
$form_id
), array(), $lead, $form );
//Disabling autoformat to prevent double autoformatting of messages
$disableAutoformat = '1';
return compact( 'to', 'from', 'bcc', 'replyTo', 'subject', 'message', 'from_name', 'message_format', 'attachments', 'disableAutoformat' );
}
public static function send_notification( $notification, $form, $lead, $data = array() ) {
GFCommon::log_debug( "GFCommon::send_notification(): Starting to process notification (#{$notification['id']} - {$notification['name']})." );
$notification = gf_apply_filters( array( 'gform_notification', $form['id'] ), $notification, $form, $lead );
$to_field = '';
if ( rgar( $notification, 'toType' ) == 'field' ) {
$to_field = rgar( $notification, 'toField' );
if ( rgempty( 'toField', $notification ) ) {
$to_field = rgar( $notification, 'to' );
}
}
$email_to = rgar( $notification, 'to' );
//do routing logic if "to" field doesn't have a value (to support legacy notifications that will run routing prior to this method)
if ( empty( $email_to ) && rgar( $notification, 'toType' ) == 'routing' ) {
$email_to = array();
foreach ( $notification['routing'] as $routing ) {
if ( rgempty( 'email', $routing ) ) {
continue;
}
GFCommon::log_debug( __METHOD__ . '(): Evaluating Routing - rule => ' . print_r( $routing, 1 ) );
$source_field = RGFormsModel::get_field( $form, rgar( $routing, 'fieldId' ) );
$field_value = RGFormsModel::get_lead_field_value( $lead, $source_field );
$is_value_match = RGFormsModel::is_value_match( $field_value, rgar( $routing, 'value', '' ), rgar( $routing, 'operator', 'is' ), $source_field, $routing, $form ) && ! RGFormsModel::is_field_hidden( $form, $source_field, array(), $lead );
if ( $is_value_match ) {
$email_to[] = $routing['email'];
}
GFCommon::log_debug( __METHOD__ . '(): Evaluating Routing - field value => ' . print_r( $field_value, 1 ) );
$is_value_match = $is_value_match ? 'Yes' : 'No';
GFCommon::log_debug( __METHOD__ . '(): Evaluating Routing - is value match? ' . $is_value_match );
}
$email_to = join( ',', $email_to );
} elseif ( ! empty( $to_field ) ) {
$source_field = RGFormsModel::get_field( $form, $to_field );
$email_to = RGFormsModel::get_lead_field_value( $lead, $source_field );
}
// Running through variable replacement
$to = GFCommon::replace_variables( $email_to, $form, $lead, false, false, true, 'html', $data );
$subject = GFCommon::replace_variables( rgar( $notification, 'subject' ), $form, $lead, false, false, true, 'text', $data );
$from = GFCommon::replace_variables( rgar( $notification, 'from' ), $form, $lead, false, false, true, 'html', $data );
$from_name = GFCommon::replace_variables( rgar( $notification, 'fromName' ), $form, $lead, false, false, true, 'text', $data );
$bcc = GFCommon::replace_variables( rgar( $notification, 'bcc' ), $form, $lead, false, false, true, 'html', $data );
$replyTo = GFCommon::replace_variables( rgar( $notification, 'replyTo' ), $form, $lead, false, false, true, 'html', $data );
/**
* Enable the CC header for the notification.
*
* @since 2.3
*
* @param bool $enable_cc Should the CC header be enabled?
* @param array $notification The current notification object.
* @param array $from The current form object.
*/
$enable_cc = gf_apply_filters( array( 'gform_notification_enable_cc', $form['id'], $notification['id'] ), false, $notification, $form );
// Set CC if enabled.
$cc = $enable_cc ? GFCommon::replace_variables( rgar( $notification, 'cc' ), $form, $lead, false, false, true, 'html', $data ) : null;
$message_format = rgempty( 'message_format', $notification ) ? 'html' : rgar( $notification, 'message_format' );
$merge_tag_format = $message_format === 'multipart' ? 'html' : $message_format;
$message = GFCommon::replace_variables( rgar( $notification, 'message' ), $form, $lead, false, false, ! rgar( $notification, 'disableAutoformat' ), $merge_tag_format, $data );
if ( apply_filters( 'gform_enable_shortcode_notification_message', true, $form, $lead ) ) {
$message = do_shortcode( $message );
}
// Allow attachments to be passed as a single path (string) or an array of paths, if string provided, add to array.
$attachments = rgar( $notification, 'attachments' );
if ( ! empty( $attachments ) ) {
$attachments = is_array( $attachments ) ? $attachments : array( $attachments );
} else {
$attachments = array();
}
if ( $message_format === 'multipart' ) {
// Creating alternate text message.
$text_message = GFCommon::replace_variables( rgar( $notification, 'message' ), $form, $lead, false, false, ! rgar( $notification, 'disableAutoformat' ), 'text', $data );
if ( apply_filters( 'gform_enable_shortcode_notification_message', true, $form, $lead ) ) {
$text_message = do_shortcode( $text_message );
}
// Formatting text message. Removes all tags.
$text_message = self::format_text_message( $text_message );
// Sends text and html messages to send_email()
$message = array(
'html' => $message,
'text' => $text_message,
);
}
self::send_email( $from, $to, $bcc, $replyTo, $subject, $message, $from_name, $message_format, $attachments, $lead, $notification, $cc );
return compact( 'to', 'from', 'bcc', 'replyTo', 'subject', 'message', 'from_name', 'message_format', 'attachments', 'cc' );
}
public static function send_notifications( $notification_ids, $form, $lead, $do_conditional_logic = true, $event = 'form_submission', $data = array() ) {
$entry_id = rgar( $lead, 'id' );
if ( ! is_array( $notification_ids ) || empty( $notification_ids ) ) {
GFCommon::log_debug( "GFCommon::send_notifications(): Aborting. No notifications to process for {$event} event for entry #{$entry_id}." );
return;
}
GFCommon::log_debug( "GFCommon::send_notifications(): Processing notifications for {$event} event for entry #{$entry_id}: " . print_r( $notification_ids, true ) . "\n(only active/applicable notifications are sent)" );
foreach ( $notification_ids as $notification_id ) {
if ( ! isset( $form['notifications'][ $notification_id ] ) ) {
continue;
}
if ( isset( $form['notifications'][ $notification_id ]['isActive'] ) && ! $form['notifications'][ $notification_id ]['isActive'] ) {
GFCommon::log_debug( "GFCommon::send_notifications(): Notification is inactive, not processing notification (#{$notification_id} - {$form['notifications'][$notification_id]['name']})." );
continue;
}
$notification = $form['notifications'][ $notification_id ];
//check conditional logic when appropriate
if ( $do_conditional_logic && ! GFCommon::evaluate_conditional_logic( rgar( $notification, 'conditionalLogic' ), $form, $lead ) ) {
GFCommon::log_debug( "GFCommon::send_notifications(): Notification conditional logic not met, not processing notification (#{$notification_id} - {$notification['name']})." );
continue;
}
if ( rgar( $notification, 'type' ) == 'user' ) {
//Getting user notification from legacy structure (for backwards compatibility)
$legacy_notification = GFCommon::prepare_user_notification( $form, $lead );
$notification = self::merge_legacy_notification( $notification, $legacy_notification );
} elseif ( rgar( $notification, 'type' ) == 'admin' ) {
//Getting admin notification from legacy structure (for backwards compatibility)
$legacy_notification = GFCommon::prepare_admin_notification( $form, $lead );
$notification = self::merge_legacy_notification( $notification, $legacy_notification );
}
//sending notification
self::send_notification( $notification, $form, $lead, $data );
}
}
public static function send_form_submission_notifications( $form, $lead ) {
GFAPI::send_notifications( $form, $lead );
}
private static function merge_legacy_notification( $notification, $notification_data ) {
$keys = array(
'to',
'from',
'bcc',
'replyTo',
'subject',
'message',
'from_name',
'message_format',
'attachments',
'disableAutoformat'
);
foreach ( $keys as $key ) {
$notification[ $key ] = rgar( $notification_data, $key );
}
return $notification;
}
public static function get_notifications_to_send( $event, $form, $lead ) {
$notifications = self::get_notifications( $event, $form );
$notifications_to_send = array();
foreach ( $notifications as $notification ) {
if ( GFCommon::evaluate_conditional_logic( rgar( $notification, 'conditionalLogic' ), $form, $lead ) ) {
$notifications_to_send[] = $notification;
}
}
return $notifications_to_send;
}
public static function get_notifications( $event, $form ) {
if ( rgempty( 'notifications', $form ) ) {
return array();
}
$notifications = array();
foreach ( $form['notifications'] as $notification ) {
$notification_event = rgar( $notification, 'event' );
$omit_from_resend = array( 'form_saved', 'form_save_email_requested' );
if ( $notification_event == $event || ( $event == 'resend_notifications' && ! in_array( $notification_event, $omit_from_resend ) ) ) {
$notifications[] = $notification;
}
}
return $notifications;
}
public static function has_admin_notification( $form ) {
return ( ! empty( $form['notification']['to'] ) || ! empty( $form['notification']['routing'] ) ) && ( ! empty( $form['notification']['subject'] ) || ! empty( $form['notification']['message'] ) );
}
public static function has_user_notification( $form ) {
return ! empty( $form['autoResponder']['toField'] ) && ( ! empty( $form['autoResponder']['subject'] ) || ! empty( $form['autoResponder']['message'] ) );
}
public static function send_email( $from, $to, $bcc, $reply_to, $subject, $message, $from_name = '', $message_format = 'html', $attachments = '', $entry = false, $notification = false, $cc = null ) {
global $phpmailer;
$to = str_replace( ' ', '', $to );
$bcc = str_replace( ' ', '', $bcc );
$cc = str_replace( ' ', '', $cc );
if ( ! GFCommon::is_valid_email( $from ) ) {
$from = get_bloginfo( 'admin_email' );
}
$error = false;
if ( ! GFCommon::is_valid_email_list( $to ) ) {
$error = new WP_Error( 'invalid_to', 'Cannot send email because the TO address is invalid.' );
} elseif ( empty( $subject ) && empty( $message ) ) {
$error = new WP_Error( 'missing_subject_and_message', 'Cannot send email because there is no SUBJECT and no MESSAGE.' );
} elseif ( ! GFCommon::is_valid_email( $from ) ) {
$error = new WP_Error( 'invalid_from', 'Cannot send email because the FROM address is invalid.' );
}
switch ( strtolower( $message_format ) ) {
case 'html' :
$content_type = 'text/html';
break;
case 'text' :
$content_type = 'text/plain';
break;
case 'multipart' :
$boundary = self::$email_boundary;
$content_type = "multipart/alternative; boundary={$boundary}";
break;
default :
//When content type is unknown, default to HTML
$content_type = 'text/html';
break;
}
if ( is_wp_error( $error ) ) {
GFCommon::log_error( 'GFCommon::send_email(): ' . $error->get_error_message() );
GFCommon::log_error( print_r( compact( 'to', 'subject', 'message' ), true ) );
/**
* Fires when an email from Gravity Forms has failed to send
*
* @since 1.8.10
*
* @param string $error The Error message returned after the email fails to send
* @param array $details The details of the message that failed
* @param array $entry The Entry object
*
*/
do_action( 'gform_send_email_failed', $error, compact( 'from', 'to', 'bcc', 'reply_to', 'subject', 'message', 'from_name', 'message_format', 'attachments', 'cc' ), $entry );
return;
}
/**
* Allows for formatting of the TO email address to improve spam score.
*
* @param bool enabled Value being filtered. Return true to format email TO, or false to leave email TO as is. Defaults to false.
*
* @since 2.2.0.3
*/
if ( apply_filters( 'gform_format_email_to', false ) ) {
// Formats email TO field to improve Spam Assassin score
$to = self::format_email_to( $to );
}
$message = self::format_email_message( $message, $message_format, $subject );
$name = empty( $from_name ) ? $from : $from_name;
$headers = array();
$headers['From'] = 'From: "' . wp_strip_all_tags( $name, true ) . '" <' . $from . '>';
if ( GFCommon::is_valid_email_list( $reply_to ) ) {
$headers['Reply-To'] = "Reply-To: {$reply_to}";
}
if ( GFCommon::is_valid_email_list( $bcc ) ) {
$headers['Bcc'] = "Bcc: $bcc";
}
if ( GFCommon::is_valid_email_list( $cc ) ) {
$headers['Cc'] = "Cc: $cc";
}
$headers['Content-type'] = "Content-type: {$content_type}; charset=" . get_option( 'blog_charset' );
$abort_email = false;
/**
* Modify the email before a notification has been sent.
* You may also use this to prevent an email from being sent.
*
* @since 2.2.3.8 Added $entry parameter.
* @since 1.9.15.6 Added $notification parameter.
* @since Unknown
*
* @param array $email An array containing the email to address, subject, message, headers, attachments and abort email flag.
* @param string $message_format The message format: html or text.
* @param array $notification The current Notification object.
* @param array $entry The current Entry object.
*/
extract( apply_filters( 'gform_pre_send_email', compact( 'to', 'subject', 'message', 'headers', 'attachments', 'abort_email' ), $message_format, $notification, $entry ) );
$is_success = false;
if ( ! $abort_email ) {
GFCommon::log_debug( 'GFCommon::send_email(): Sending email via wp_mail().' );
GFCommon::log_debug( print_r( compact( 'to', 'subject', 'message', 'headers', 'attachments', 'abort_email' ), true ) );
// Content type filter is needed to get around a bug in WordPress that ignores the boundary attribute and character set.
add_filter( 'wp_mail_content_type', array( 'GFCommon', 'set_content_type_boundary' ) );
add_filter( 'wp_mail_charset', array( 'GFCommon', 'set_mail_charset' ) );
// Sending email.
$is_success = wp_mail( $to, $subject, $message, $headers, $attachments );
// Removing filter. It is only needed when sending GF notifications.
remove_filter( 'wp_mail_content_type', array( 'GFCommon', 'set_content_type_boundary' ) );
remove_filter( 'wp_mail_charset', array( 'GFCommon', 'set_mail_charset' ) );
$result = is_wp_error( $is_success ) ? $is_success->get_error_message() : $is_success;
GFCommon::log_debug( "GFCommon::send_email(): Result from wp_mail(): {$result}" );
if ( ! is_wp_error( $is_success ) && $is_success ) {
GFCommon::log_debug( 'GFCommon::send_email(): Mail was passed from WordPress to the mail server.' );
} else {
GFCommon::log_error( 'GFCommon::send_email(): The mail message was passed off to WordPress for processing, but WordPress was unable to send the message.' );
}
if ( has_filter( 'phpmailer_init' ) ) {
GFCommon::log_debug( __METHOD__ . '(): The WordPress phpmailer_init hook has been detected, usually used by SMTP plugins, it can impact mail delivery.' );
}
if ( ! empty( $phpmailer->ErrorInfo ) ) {
GFCommon::log_debug( __METHOD__ . '(): PHPMailer class returned an error message: ' . print_r( $phpmailer->ErrorInfo, 1 ) );
}
} else {
GFCommon::log_debug( 'GFCommon::send_email(): Aborting. The gform_pre_send_email hook was used to set the abort_email parameter to true.' );
}
self::add_emails_sent();
/**
* Fires after an email is sent
*
* @param bool $is_success True is successfully sent. False if failed
* @param string $to Recipient address
* @param string $subject Subject line
* @param string $message Message body
* @param string $headers Email headers
* @param string $attachments Email attachments
* @param string $message_format Format of the email. Ex: text, html
* @param string $from Address of the sender
* @param string $from_name Displayed name of the sender
* @param string $bcc BCC recipients
* @param string $reply_to Reply-to address
* @param array $entry Entry object associated with the sent email
* @param string $cc CC recipients
*
*/
do_action( 'gform_after_email', $is_success, $to, $subject, $message, $headers, $attachments, $message_format, $from, $from_name, $bcc, $reply_to, $entry, $cc );
}
/**
* Sets the boundary attribute of the Content-type email header.
* This is a target of the wp_mail_content_type filter and is needed to get around a WordPress bug
* That ignores the boundary attribute if added to the $headers parameter of wp_mail().
*
* @since 2.2
*
* @param $content_type Content type to be filtered
*
* @return string
*/
public static function set_content_type_boundary( $content_type ) {
if ( $content_type === 'multipart/alternative' ) {
$boundary = GFCommon::$email_boundary;
$content_type = "{$content_type}; boundary={$boundary}";
}
return $content_type;
}
/**
* Sets the character set email header.
*
* This is a target of the wp_mail_charset filter and is needed to get around a WordPress bug
* that ignores the charset attribute if added to the $headers parameter of wp_mail().
*
* @since 2.2
*
* @param string $charset Character set to be filtered.
*
* @return string
*/
public static function set_mail_charset( $charset ) {
if ( empty( $charset ) ) {
$charset = get_option( 'blog_charset' );
}
return $charset;
}
/**
* Formats emails to improve Spam Assassin score.
*
* @since 2.2
*
* @param string $to Email or comma separated list of emails to be formatted
*
* @return string
*/
private static function format_email_to( $to ) {
$emails = explode( ',', $to );
$email_list = array();
foreach ( $emails as $email ) {
if ( empty( $email ) ) {
continue;
}
// Formatting To to improve Spam Assassin score
if ( strpos( $email, '<' ) === false ) {
$email_list[] = "\"{$email}\" <$email>";
}
}
return implode( ',', $email_list );
}
/**
* Formats the email message to improve Spam Assassin score.
*
* @since 2.2
*
* @param string $message Email message to be formatted.
* @param string $message_format Format of the message to be sent. 'text' or 'html'.
* @param string $subject Email subject.
*
* @return string
*/
private static function format_email_message( $message, $message_format, $subject ) {
switch ( strtolower( $message_format ) ) {
case 'html' :
// Formatting HTML message
$message = self::format_html_message( $message, $subject );
return $message;
break;
case 'text' :
// No format needed for text messages
return $message;
break;
case 'multipart' :
$html_message = self::format_html_message( $message['html'], $subject );
$text_message = $message['text'];
$boundary = self::$email_boundary;
// Formatting multipart message
$message = "--{$boundary}
Content-Type: text/plain;
{$text_message}
--{$boundary}
Content-Type: text/html;
{$html_message}
--{$boundary}--";
return $message;
break;
default :
return $message;
}
}
public static function add_emails_sent() {
$count = self::get_emails_sent();
update_option( 'gform_email_count', ++ $count );
}
public static function get_emails_sent() {
$count = get_option( 'gform_email_count' );
if ( ! $count ) {
$count = 0;
}
return $count;
}
public static function get_api_calls() {
$count = get_option( 'gform_api_count' );
if ( ! $count ) {
$count = 0;
}
return $count;
}
public static function add_api_call() {
$count = self::get_api_calls();
update_option( 'gform_api_count', ++ $count );
}
public static function has_post_field( $fields ) {
foreach ( $fields as $field ) {
if ( in_array( $field->type, array(
'post_title',
'post_content',
'post_excerpt',
'post_category',
'post_image',
'post_tags',
'post_custom_field'
) ) ) {
return true;
}
}
return false;
}
public static function has_list_field( $form ) {
return self::has_field_by_type( $form, 'list' );
}
public static function has_credit_card_field( $form ) {
return self::has_field_by_type( $form, 'creditcard' );
}
private static function has_field_by_type( $form, $type ) {
if ( is_array( $form['fields'] ) ) {
foreach ( $form['fields'] as $field ) {
if ( RGFormsModel::get_input_type( $field ) == $type ) {
return true;
}
}
}
return false;
}
/***
* Determines if the current user has the proper cabalities to uninstall the plugin specified in $plugin_path.
* Plugins that have been network activated can only be uninstalled by a network admin.
*
* @since 2.3.1.12
* @access public
*
* @param string $caps Capabilities that current user must have to be able to uninstall the plugin.
* @param string $plugin_path Path of the plugin to be checked, relative to the plugins folder. i.e. "gravityforms/gravityforms.php"
*
* @return bool True if current user can uninstall the plugin. False otherwise
*/
public static function current_user_can_uninstall( $caps = 'gravityforms_uninstall', $plugin_path = 'gravityforms/gravityforms.php' ) {
$is_multisite = function_exists( 'is_multisite' ) && is_multisite();
$is_network_activated = is_plugin_active_for_network( $plugin_path );
//If an addon is network activated, it can only be uninstalled by a super admin.
if ( $is_multisite && $is_network_activated ) {
return is_super_admin();
} else {
return self::current_user_can_any( $caps );
}
}
public static function current_user_can_any( $caps ) {
if ( ! is_array( $caps ) ) {
$has_cap = current_user_can( $caps ) || current_user_can( 'gform_full_access' );
return $has_cap;
}
foreach ( $caps as $cap ) {
if ( current_user_can( $cap ) ) {
return true;
}
}
$has_full_access = current_user_can( 'gform_full_access' );
return $has_full_access;
}
public static function current_user_can_which( $caps ) {
foreach ( $caps as $cap ) {
if ( current_user_can( $cap ) ) {
return $cap;
}
}
return '';
}
public static function is_pricing_field( $field_type ) {
return self::is_product_field( $field_type ) || $field_type == 'donation';
}
/**
* Checks if a field is a product field.
*
* @access public
* @since 2.1.1.12 Added support for hiddenproduct, singleproduct, and singleshipping input types.
*
* @param string $field_type The field type.
*
* @return bool Returns true if it is a product field. Otherwise, false.
*/
public static function is_product_field( $field_type ) {
/**
* Filters the input types to use when checking if a field is a product field.
*
* @since 2.1.1.12 Added support for hiddenproduct, singleproduct, and singleshipping input types.
* @since 1.9.14
*
* @param $product_fields The product field types.
*/
$product_fields = apply_filters( 'gform_product_field_types', array(
'option',
'quantity',
'product',
'total',
'shipping',
'calculation',
'price',
'hiddenproduct',
'singleproduct',
'singleshipping'
) );
return in_array( $field_type, $product_fields );
}
/**
* Returns all the plugin capabilities.
*
* @since 2.2.1.12 Added gravityforms_system_status.
* @since unknown
*
* @return array
*/
public static function all_caps() {
return array(
'gravityforms_edit_forms',
'gravityforms_delete_forms',
'gravityforms_create_form',
'gravityforms_view_entries',
'gravityforms_edit_entries',
'gravityforms_delete_entries',
'gravityforms_view_settings',
'gravityforms_edit_settings',
'gravityforms_export_entries',
'gravityforms_uninstall',
'gravityforms_view_entry_notes',
'gravityforms_edit_entry_notes',
'gravityforms_view_updates',
'gravityforms_view_addons',
'gravityforms_preview_forms',
'gravityforms_system_status',
);
}
public static function delete_directory( $dir ) {
if ( ! file_exists( $dir ) ) {
return;
}
if ( $handle = opendir( $dir ) ) {
$array = array();
while ( false !== ( $file = readdir( $handle ) ) ) {
if ( $file != '.' && $file != '..' ) {
if ( is_dir( $dir . $file ) ) {
if ( ! @rmdir( $dir . $file ) ) {
// Empty directory? Remove it
self::delete_directory( $dir . $file . '/' );
} // Not empty? Delete the files inside it
} else {
@unlink( $dir . $file );
}
}
}
closedir( $handle );
@rmdir( $dir );
}
}
public static function get_remote_message() {
return stripslashes( get_option( 'rg_gforms_message' ) );
}
public static function get_key() {
return get_option( 'rg_gforms_key' );
}
public static function has_update( $use_cache = true ) {
$version_info = GFCommon::get_version_info( $use_cache );
$version = rgar( $version_info, 'version' );
return empty( $version ) ? false : version_compare( GFCommon::$version, $version, '<' );
}
public static function get_key_info( $key ) {
$options = array( 'method' => 'POST', 'timeout' => 3 );
$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' )
);
$raw_response = self::post_to_manager( 'api.php', "op=get_key&key={$key}", $options );
if ( is_wp_error( $raw_response ) || $raw_response['response']['code'] != 200 ) {
return array();
}
$key_info = unserialize( trim( $raw_response['body'] ) );
return $key_info ? $key_info : array();
}
public static function get_version_info( $cache = true ) {
$version_info = get_option( 'gform_version_info' );
if ( ! $cache ) {
$version_info = null;
} else {
// Checking cache expiration
$cache_duration = DAY_IN_SECONDS; // 24 hours.
$cache_timestamp = $version_info && isset( $version_info['timestamp'] ) ? $version_info['timestamp'] : 0;
// Is cache expired ?
if ( $cache_timestamp + $cache_duration < time() ) {
$version_info = null;
}
}
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 ( ! $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' ),
'Referer' => get_bloginfo( 'url' ),
);
$options['body'] = self::get_remote_post_params();
$options['timeout'] = 15;
$nocache = $cache ? '' : 'nocache=1'; //disabling server side caching
$raw_response = self::post_to_manager( 'version.php', $nocache, $options );
if ( is_wp_error( $raw_response ) || rgars( $raw_response, 'response/code' ) != 200 ) {
$version_info = array( 'is_valid_key' => '1', 'version' => '', 'url' => '', 'is_error' => '1' );
} else {
$version_info = json_decode( $raw_response['body'], true );
if ( empty( $version_info ) ) {
$version_info = array( 'is_valid_key' => '1', 'version' => '', 'url' => '', 'is_error' => '1' );
}
}
$version_info['timestamp'] = time();
// Caching response.
update_option( 'gform_version_info', $version_info ); //caching version info
}
return $version_info;
}
public static function get_remote_request_params() {
global $wpdb;
return sprintf( 'of=GravityForms&key=%s&v=%s&wp=%s&php=%s&mysql=%s&version=2', urlencode( self::get_key() ), urlencode( self::$version ), urlencode( get_bloginfo( 'version' ) ), urlencode( phpversion() ), urlencode( $wpdb->db_version() ) );
}
public static function get_remote_post_params() {
global $wpdb;
if ( ! function_exists( 'get_plugins' ) ) {
require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
}
$plugin_list = get_plugins();
$site_url = get_bloginfo( 'url' );
$plugins = array();
$active_plugins = get_option( 'active_plugins' );
foreach ( $plugin_list as $key => $plugin ) {
$is_active = in_array( $key, $active_plugins );
$slug = substr( $key, 0, strpos( $key, '/' ) );
if ( empty( $slug ) ) {
$slug = str_replace( '.php', '', $key );
}
$plugins[] = array(
'name' => str_replace( 'phpinfo()', 'PHP Info', $plugin['Name'] ),
'slug' => $slug,
'version' => $plugin['Version'],
'is_active' => $is_active,
);
}
$plugins = json_encode( $plugins );
//get theme info
$theme = wp_get_theme();
$theme_name = $theme->get( 'Name' );
$theme_uri = $theme->get( 'ThemeURI' );
$theme_version = $theme->get( 'Version' );
$theme_author = $theme->get( 'Author' );
$theme_author_uri = $theme->get( 'AuthorURI' );
$form_counts = GFFormsModel::get_form_count();
$active_count = $form_counts['active'];
$inactive_count = $form_counts['inactive'];
$fc = abs( $active_count ) + abs( $inactive_count );
$entry_count = GFFormsModel::get_entry_count_all_forms( 'active' );
$meta_counts = GFFormsModel::get_entry_meta_counts();
$im = is_multisite();
$lang = get_locale();
$post = array(
'of' => 'gravityforms',
'key' => self::get_key(),
'v' => self::$version,
'wp' => get_bloginfo( 'version' ),
'php' => phpversion(),
'mysql' => $wpdb->db_version(),
'version' => '2',
'plugins' => $plugins,
'tn' => $theme_name,
'tu' => $theme_uri,
'tv' => $theme_version,
'ta' => $theme_author,
'tau' => $theme_author_uri,
'im' => $im,
'fc' => $fc,
'ec' => $entry_count,
'emc' => self::get_emails_sent(),
'api' => self::get_api_calls(),
'emeta' => $meta_counts['meta'],
'ed' => $meta_counts['details'],
'en' => $meta_counts['notes'],
'lang' => $lang
);
return $post;
}
public static function ensure_wp_version() {
if ( ! GF_SUPPORTED_WP_VERSION ) {
echo "
" . sprintf( esc_html__( 'Gravity Forms requires WordPress %s or greater. You must upgrade WordPress in order to use Gravity Forms', 'gravityforms' ), GF_MIN_WP_VERSION ) . '
';
return false;
}
return true;
}
public static function check_update( $option, $cache = true ) {
if ( ! is_object( $option ) ) {
return $option;
}
$version_info = self::get_version_info( $cache );
if ( ! $version_info ) {
return $option;
}
$plugin_path = 'gravityforms/gravityforms.php';
if ( empty( $option->response[ $plugin_path ] ) ) {
$option->response[ $plugin_path ] = new stdClass();
}
$version = rgar( $version_info, 'version' );
//Empty response means that the key is invalid. Do not queue for upgrade
if ( ! rgar( $version_info, 'is_valid_key' ) || version_compare( GFCommon::$version, $version, '>=' ) ) {
unset( $option->response[ $plugin_path ] );
} else {
$url = rgar( $version_info, 'url' );
$option->response[ $plugin_path ]->url = 'http://www.gravityforms.com';
$option->response[ $plugin_path ]->slug = 'gravityforms';
$option->response[ $plugin_path ]->plugin = $plugin_path;
$option->response[ $plugin_path ]->package = str_replace( '{KEY}', GFCommon::get_key(), $url );
$option->response[ $plugin_path ]->new_version = $version;
$option->response[ $plugin_path ]->id = '0';
}
return $option;
}
public static function cache_remote_message() {
//Getting version number
$key = GFCommon::get_key();
$body = "key=$key";
$options = array( 'method' => 'POST', 'timeout' => 3, 'body' => $body );
$options['headers'] = array(
'Content-Type' => 'application/x-www-form-urlencoded; charset=' . get_option( 'blog_charset' ),
'Content-Length' => strlen( $body ),
'User-Agent' => 'WordPress/' . get_bloginfo( 'version' ),
'Referer' => get_bloginfo( 'url' )
);
$raw_response = self::post_to_manager( 'message.php', GFCommon::get_remote_request_params(), $options );
if ( is_wp_error( $raw_response ) || 200 != $raw_response['response']['code'] ) {
$message = '';
} else {
$message = $raw_response['body'];
}
//validating that message is a valid Gravity Form message. If message is invalid, don't display anything
if ( substr( $message, 0, 10 ) != '' ) {
$message = '';
}
update_option( 'rg_gforms_message', $message );
}
public static function post_to_manager( $file, $query, $options ) {
$request_url = GRAVITY_MANAGER_URL . '/' . $file . '?' . $query;
self::log_debug( __METHOD__ . '(): endpoint: ' . $request_url );
$raw_response = wp_remote_post( $request_url, $options );
self::log_remote_response( $raw_response );
if ( is_wp_error( $raw_response ) || 200 != $raw_response['response']['code'] ) {
self::log_error( __METHOD__ . '(): Error from manager. Sending to proxy...' );
$request_url = GRAVITY_MANAGER_PROXY_URL . '/proxy.php?f=' . $file . '&' . $query;
$raw_response = wp_remote_post( $request_url, $options );
self::log_remote_response( $raw_response );
}
return $raw_response;
}
/**
* Converts the given timestamp to a pseudo timestamp which has been adjusted for the timezone in the WordPress settings.
*
*
* @param int $timestamp
*
* @return int
*/
public static function get_local_timestamp( $timestamp = null ) {
if ( $timestamp == null ) {
$timestamp = time();
}
$gmt_datetime = gmdate( 'Y-m-d H:i:s', $timestamp );
return strtotime( get_date_from_gmt( $gmt_datetime ) );
}
public static function get_gmt_timestamp( $local_timestamp ) {
return $local_timestamp - ( get_option( 'gmt_offset' ) * 3600 );
}
public static function format_date( $gmt_datetime, $is_human = true, $date_format = '', $include_time = true ) {
if ( empty( $gmt_datetime ) ) {
return '';
}
//adjusting date to local configured Time Zone
$lead_gmt_time = mysql2date( 'G', $gmt_datetime );
$lead_local_time = self::get_local_timestamp( $lead_gmt_time );
if ( empty( $date_format ) ) {
$date_format = get_option( 'date_format' );
}
if ( $is_human ) {
$time_diff = time() - $lead_gmt_time;
if ( $time_diff > 0 && $time_diff < 24 * 60 * 60 ) {
$date_display = sprintf( esc_html__( '%s ago', 'gravityforms' ), human_time_diff( $lead_gmt_time ) );
} else {
$date_display = $include_time ? sprintf( esc_html__( '%1$s at %2$s', 'gravityforms' ), date_i18n( $date_format, $lead_local_time, true ), date_i18n( get_option( 'time_format' ), $lead_local_time, true ) ) : date_i18n( $date_format, $lead_local_time, true );
}
} else {
$date_display = $include_time ? sprintf( esc_html__( '%1$s at %2$s', 'gravityforms' ), date_i18n( $date_format, $lead_local_time, true ), date_i18n( get_option( 'time_format' ), $lead_local_time, true ) ) : date_i18n( $date_format, $lead_local_time, true );
}
return $date_display;
}
public static function get_selection_value( $value ) {
$ary = explode( '|', $value );
$val = $ary[0];
return $val;
}
public static function selection_display( $value, $field, $currency = '', $use_text = false ) {
if ( is_array( $value ) ) {
return '';
}
if ( $field !== null && $field->enablePrice ) {
$ary = explode( '|', $value );
$val = $ary[0];
$price = count( $ary ) > 1 ? $ary[1] : '';
} else {
$val = $value;
$price = '';
}
if ( $use_text ) {
$val = RGFormsModel::get_choice_text( $field, $val );
}
if ( ! empty( $price ) ) {
return "$val (" . self::to_money( $price, $currency ) . ')';
} else {
return $val;
}
}
public static function date_display( $value, $input_format = 'mdy', $output_format = false ) {
if ( ! $output_format ) {
$output_format = $input_format;
}
$date = self::parse_date( $value, $input_format );
if ( empty( $date ) ) {
return $value;
}
list( $position, $separator ) = rgexplode( '_', $output_format, 2 );
switch ( $separator ) {
case 'dash' :
$separator = '-';
break;
case 'dot' :
$separator = '.';
break;
default :
$separator = '/';
break;
}
switch ( $position ) {
case 'year' :
case 'month' :
case 'day' :
return $date[ $position ];
case 'ymd' :
return $date['year'] . $separator . $date['month'] . $separator . $date['day'];
break;
case 'dmy' :
return $date['day'] . $separator . $date['month'] . $separator . $date['year'];
break;
default :
return $date['month'] . $separator . $date['day'] . $separator . $date['year'];
break;
}
}
public static function parse_date( $date, $format = 'mdy' ) {
$date_info = array();
$position = substr( $format, 0, 3 );
if ( is_array( $date ) ) {
switch ( $position ) {
case 'mdy' :
$date_info['month'] = rgar( $date, 0 );
$date_info['day'] = rgar( $date, 1 );
$date_info['year'] = rgar( $date, 2 );
break;
case 'dmy' :
$date_info['day'] = rgar( $date, 0 );
$date_info['month'] = rgar( $date, 1 );
$date_info['year'] = rgar( $date, 2 );
break;
case 'ymd' :
$date_info['year'] = rgar( $date, 0 );
$date_info['month'] = rgar( $date, 1 );
$date_info['day'] = rgar( $date, 2 );
break;
}
return $date_info;
}
$date = preg_replace( "|[/\.]|", '-', $date );
if ( preg_match( '/^(\d{1,4})-(\d{1,2})-(\d{1,4})$/', $date, $matches ) ) {
if ( strlen( $matches[1] ) == 4 ) {
//format yyyy-mm-dd
$date_info['year'] = $matches[1];
$date_info['month'] = $matches[2];
$date_info['day'] = $matches[3];
} else if ( $position == 'mdy' ) {
//format mm-dd-yyyy
$date_info['month'] = $matches[1];
$date_info['day'] = $matches[2];
$date_info['year'] = $matches[3];
} else {
//format dd-mm-yyyy
$date_info['day'] = $matches[1];
$date_info['month'] = $matches[2];
$date_info['year'] = $matches[3];
}
}
return $date_info;
}
public static function truncate_url( $url ) {
$truncated_url = basename( $url );
if ( empty( $truncated_url ) ) {
$truncated_url = dirname( $url );
}
$ary = explode( '?', $truncated_url );
return $ary[0];
}
public static function get_field_placeholder_attribute( $field ) {
$placeholder_value = GFCommon::replace_variables_prepopulate( $field->placeholder );
return ! empty( $placeholder_value ) ? sprintf( "placeholder='%s'", esc_attr( $placeholder_value ) ) : '';
}
public static function get_input_placeholder_attribute( $input ) {
$placeholder_value = self::get_input_placeholder_value( $input );
return ! empty( $placeholder_value ) ? sprintf( "placeholder='%s'", esc_attr( $placeholder_value ) ) : '';
}
public static function get_input_placeholder_value( $input ) {
$placeholder = rgar( $input, 'placeholder' );
return empty( $placeholder ) ? '' : GFCommon::replace_variables_prepopulate( $placeholder );
}
public static function get_tabindex() {
return GFCommon::$tab_index > 0 ? "tabindex='" . GFCommon::$tab_index ++ . "'" : '';
}
/**
* @deprecated
*
* @param GF_Field_Checkbox $field
* @param $value
* @param $disabled_text
*
* @return mixed
*/
public static function get_checkbox_choices( $field, $value, $disabled_text ) {
_deprecated_function( 'get_checkbox_choices', '1.9', 'GF_Field_Checkbox::get_checkbox_choices' );
return $field->get_checkbox_choices( $value, $disabled_text );
}
/**
* @deprecated Deprecated since 1.9. Use GF_Field_Checkbox::get_radio_choices() instead.
*
* @param GF_Field_Radio $field
* @param string $value
* @param $disabled_text
*
* @return mixed
*/
public static function get_radio_choices( $field, $value = '', $disabled_text ) {
_deprecated_function( 'get_radio_choices', '1.9', 'GF_Field_Checkbox::get_radio_choices' );
return $field->get_radio_choices( $value, $disabled_text );
}
public static function get_field_type_title( $type ) {
$gf_field = GF_Fields::get( $type );
if ( ! empty( $gf_field ) ) {
return $gf_field->get_form_editor_field_title();
}
return apply_filters( 'gform_field_type_title', $type, $type );
}
public static function get_select_choices( $field, $value = '', $support_placeholders = true ) {
$choices = '';
if ( rgget('view') == 'entry' && empty( $value ) && empty( $field->placeholder ) ) {
$choices .= "";
}
if ( is_array( $field->choices ) ) {
if ( $support_placeholders && ! empty( $field->placeholder ) ) {
$selected = empty( $value ) ? "selected='selected'" : '';
$choices .= sprintf( "", $selected, esc_html( $field->placeholder ) );
}
foreach ( $field->choices as $choice ) {
//needed for users upgrading from 1.0
$field_value = ! empty( $choice['value'] ) || $field->enableChoiceValue || $field->type == 'post_category' ? $choice['value'] : $choice['text'];
if ( $field->enablePrice ) {
$price = rgempty( 'price', $choice ) ? 0 : GFCommon::to_number( rgar( $choice, 'price' ) );
$field_value .= '|' . $price;
}
if ( ! isset( $_GET['gf_token'] ) && empty( $_POST ) && self::is_empty_array( $value ) && rgget('view') != 'entry' ) {
$selected = rgar( $choice, 'isSelected' ) ? "selected='selected'" : '';
} else {
if ( is_array( $value ) ) {
$is_match = false;
foreach ( $value as $item ) {
if ( RGFormsModel::choice_value_match( $field, $choice, $item ) ) {
$is_match = true;
break;
}
}
$selected = $is_match ? "selected='selected'" : '';
} else {
$selected = RGFormsModel::choice_value_match( $field, $choice, $value ) ? "selected='selected'" : '';
}
}
$choice_markup = sprintf( "", esc_attr( $field_value ), $selected, esc_html( $choice['text'] ) );
$choices .= gf_apply_filters( array(
'gform_field_choice_markup_pre_render',
$field->formId,
$field->id
), $choice_markup, $choice, $field, $value );
}
}
return $choices;
}
public static function is_section_empty( $section_field, $form, $entry ) {
$cache_key = "GFCommon::is_section_empty_{$form['id']}_{$section_field->id}";
$value = GFCache::get( $cache_key, $is_hit, false );
if ( $value !== false ) {
return $value == true;
}
$fields = self::get_section_fields( $form, $section_field->id );
if ( ! is_array( $fields ) ) {
GFCache::set( $cache_key, 1 );
return true;
}
foreach ( $fields as $field ) {
$value = GFFormsModel::get_lead_field_value( $entry, $field );
$value = GFCommon::get_lead_field_display( $field, $value, rgar( $entry, 'currency' ) );
if ( rgblank( $value ) ) {
continue;
}
// most fields are displayed in the section by default, exceptions are handled below
$is_field_displayed_in_section = true;
// by default, product fields are not displayed in their containing section (displayed in a product summary table)
// if the filter is used to disable this, product fields are displayed in the section like other fields
if ( self::is_product_field( $field->type ) ) {
/**
* By default, product fields are not displayed in their containing section (displayed in a product summary table). If the filter is used to disable this, product fields are displayed in the section like other fields
*
* @param array $field The Form Fields Object
* @param array $form The Form Object
* @param array $entry The Entry object
*
*/
$display_product_summary = apply_filters( 'gform_display_product_summary', true, $field, $form, $entry );
$is_field_displayed_in_section = ! $display_product_summary;
}
if ( $is_field_displayed_in_section ) {
GFCache::set( $cache_key, 0 );
return false;
}
}
GFCache::set( $cache_key, 1 );
return true;
}
public static function get_section_fields( $form, $section_field_id ) {
$fields = array();
$in_section = false;
foreach ( $form['fields'] as $field ) {
if ( in_array( $field->type, array( 'section', 'page' ) ) && $in_section ) {
return $fields;
}
if ( $field->id == $section_field_id ) {
$in_section = true;
}
if ( $in_section ) {
$fields[] = $field;
}
}
return $fields;
}
public static function get_us_state_code( $state_name ) {
return GF_Fields::get( 'address' )->get_us_state_code( $state_name );
}
public static function get_country_code( $country_name ) {
return GF_Fields::get( 'address' )->get_country_code( $country_name );
}
public static function get_us_states() {
return GF_Fields::get( 'address' )->get_us_states();
}
public static function get_canadian_provinces() {
return GF_Fields::get( 'address' )->get_canadian_provinces();
}
public static function is_post_field( $field ) {
return in_array( $field->type, array(
'post_title',
'post_tags',
'post_category',
'post_custom_field',
'post_content',
'post_excerpt',
'post_image'
) );
}
public static function get_fields_by_type( $form, $types ) {
return GFAPI::get_fields_by_type( $form, $types );
}
public static function has_pages( $form ) {
return sizeof( GFAPI::get_fields_by_type( $form, array( 'page' ) ) ) > 0;
}
public static function get_product_fields_by_type( $form, $types, $product_id ) {
global $_product_fields;
$key = json_encode( $types ) . '_' . $product_id . '_' . $form['id'];
if ( ! isset( $_product_fields[ $key ] ) ) {
$fields = array();
for ( $i = 0, $count = sizeof( $form['fields'] ); $i < $count; $i ++ ) {
$field = $form['fields'][ $i ];
if ( in_array( $field->type, $types ) && $field->productField == $product_id ) {
$fields[] = $field;
}
}
$_product_fields[ $key ] = $fields;
}
return $_product_fields[ $key ];
}
public static function form_page_title( $form ) {
$editable_class = GFCommon::current_user_can_any( 'gravityforms_edit_forms' ) ? ' gform_settings_page_title_editable' : '';
?>
";
}
}
/**
* Filters the field input markup.
*
* @since 2.1.2.14 Added form and field ID modifiers.
*
* @param string empty The markup. Defaults to an empty string.
* @param array $field The Field Object.
* @param int $lead_id The entry ID.
* @param string $value The field value.
* @param int $form_id The form ID.
*/
$field_input = gf_apply_filters( array( 'gform_field_input', $form['id'], $field->id ), '', $field, $value, $lead_id, $form_id );
if ( $field_input ) {
return $field_input;
}
// Product fields are not editable
if ( rgget('view') == 'entry' && self::is_product_field( $field->type ) ) {
return "
" . esc_html__( 'Product fields are not editable' , 'gravityforms' ) . '