diff --git a/change_log.txt b/change_log.txt
index 2ff0fef..5ff17a9 100644
--- a/change_log.txt
+++ b/change_log.txt
@@ -1,3 +1,119 @@
+-------------------------------------------------------------------------------------------------------------------
+Version 1.8.13
+ - Added additional check plus user feedback for failed multi-file uploads.
+ - Fixed a potential security vulnerability for some server configurations which could allow code to be executed via the file upload field.
+ - Fixed issue with form export/import setting inactive notifications to active.
+ - Fixed issue with resend notification not accepting a list of emails.
+ - Fixed another issue with field label for Name and Address fields.
+ - Fixed issue with field label for Name and Address fields.
+ - Fixed issue causing checkboxes checked by default to be rendered unchecked in certain situations.
+
+ - AF: Fixed another issue with simple_condition() function/feature creating javascript errors.
+ - AF: Fixed get_field_map_fields function to no longer include the text "field_map" in the mapped fields prefix.
+ - AF: Fixed issue with payments less than $1.00 not being processed.
+
+-------------------------------------------------------------------------------------------------------------------
+Version 1.8.12
+ - Added PHP version of the "gform_calculation_result" filter.
+ add_filter( 'gform_calculation_result', 'my_calc_result', 10, 5 );
+ function my_calc_result( $result, $formula, $field, $form, $entry ) {
+ // modify result as needed
+ return $result;
+ }
+ - Updated chosen js, styles and images to latest version.
+ - Fixed issue with multiple file upload merge tag not including a line break when in html format.
+ - Fixed issue with List field markup; more
than
.
+ - Fixed markup validation issue with List Field where label for attribute did not match a valid input.
+ - AF: Fixed issue with simple_condition() function/feature creating javascript errors.
+ - AF: Added a check in the maybe_process_callback function to see if the callback has been aborted to prevent processing for the Payment Add-On.
+ - API: Added GFAPI::get_forms() method.
+
+-------------------------------------------------------------------------------------------------------------------
+Version 1.8.11
+
+ - Fixed issue where
tags were closed incorrectly generating invalid HTML markup.
+ - Fixed issue with notifications not being sent when configured with multiple email addresses.
+ - Fixed issue with legacy notifications getting marked as inactive after being edited.
+
+-------------------------------------------------------------------------------------------------------------------
+Version 1.8.10
+
+ - Added gform_enable_shortcode_notification_message hook to allow for disabling shortcode processing of notification messages.
+ - Added $field_values as a third paramater for the gform_pre_render filter.
+ - Added new hook: 'gform_send_email_failed'; allows interception when a call to GFCommon::send_email() fails.
+ add_action( 'gform_send_email_failed', 'my_send_email_failed_func', 10, 2 );
+ function my_send_email_failed_func( $error, $email ) {
+ // do what you want with the $error and $email data.
+ }
+ - Added new JS filter: 'gform_calculation_formula' to allow modifying formula before it is processed by GF on frontend.
+ gform.addFilter( 'gform_calculation_formula', function( formula, formulaField, formId, calcObj ) {
+ // custom code here
+ return formula;
+ } );
+ - Added $rule and $form parameters to the gform_is_value_match filter.
+ - Added GFCommon::esc_like() method to fix deprecation notice in WP 4.0 while maintining backwards compatibility with previous WP versions.
+ - Added condition to not include "gform_chosen" if "chosen" is already enqueued.
+
+ - Updated gf_reset_to_default() to not select disabled options in drop downs when reseting default value.
+ - Updated GCommon::is_valid_url() to use filter_var( $url, FILTER_VALIDATE_URL ).
+ - Updated GCommon::is_valid_email() to use filter_var( $email, FILTER_VALIDATE_EMAIL ).
+ - Updated entry details payment information markup.
+ - Updated complete_payment function to update the entry's payment_amount, transaction_id, and payment_date for the Payment Add-On.
+ - Updated process for enqueuing chosen script to check if "chosen" is a registered handle and if so to include it instead of "gform_chosen".
+ - Updated french translation.
+ - Updated product calculation field to allow the label to be changed dynamically like the single product field.
+ - Updated delete_leads_by_form function to include deleting data from the lead meta table.
+
+ - API: Updated GFAPI::get_entries() to include field choice texts in addition to values when performing a global search.
+
+ - Fixed fatal error triggered on some servers.
+ - Fixed Notice message.
+ - Fixed an issue with multi-page, ajax-enabled forms with images as buttons where multiple spinners were displayed during form submission.
+ - Fixed issue with multi file upload merge tag.
+ - Fixed issue with confirmation type "Page" when permalink contains a query string.
+ - Fixed bug with default values for conditional logic where any choice with a 'price' attr set (even if it wasn't a pricing field) was incorrectly treated as a pricing value.
+ - Fixed a issue with GFCommon::esc_like() causing a fatal error on WordPress < 4.0.
+ - Fixed an issue with checkbox, radio button and drop-down fields which caused data to be saved incorrectly if a pipe ("|") was used in a choice value.
+ - Fixed the validation of the website field to accept commas in the path.
+ - Fixed notices thrown in WP 4.0 on pages using/extending WP_List_Table.
+ - Fixed an issue affecting the search function on the entry list and the conditional logic on the entry export page where field choice values would be taken into account but not their corresponding texts/labels while performing a global search based on any form field. This affects all radio, checkbox and drop-down fields plus derivative fields in add-ons i.e. Poll, Survey and Quiz fields.
+ - Fixed a bug with conditional logic animation in Firefox.
+ - Fixed "Index too large" error for payment addons.
+ - Fixed issue with inactive notifications getting changed back to active when notification is edited.
+ - Fixed issue where admin label was not used for fields in the inactive column on the "Select Columns" ui.
+ - Fixed issue where is_section_empty() returned true even if section contained a product field and 'gform_display_product_summary' filter returned false.
+ - Fixed issue where tags were being displayed on notifications even when the message type was set to "text".
+ - Fixed notice thrown in update_confirmation function when isDefault not set.
+ - Fixed warnings thrown in get_version_info when the response is not an array.
+
+ - AF: Fixed issue with sales page where payment method drop down displayed blank values.
+ - AF: Fixed issue when creating subscriptions upon first subscription payment.
+ - AF: Fixed issue with payment going to gateway when the amount was negative.
+ - AF: Updated payment Add-On so that redirect_url() is called earlier in the page life-cycle.
+ - AF: Fixed issue with results page displaying an error message for the Stripe Add-On.
+ - AF: Added support for checkbox item callback to allow an individual checkbox item to be customized.
+ - AF: Fixed issue that caused a $0.00 total when selecting the same product field for the subscription payment and trial payment.
+ - AF: Fixed issue with plugin settings page displaying slug instead of Title.
+ - AF: Fixed issue with payment add-on sending requests to payment gateways even when payment was $0.00.
+ - AF: Updated process_capture function to set is_fulfilled to true so complete_payment function uses the entry value for Payment Add-On.
+ - AF: Updated maybe_process_feed function to handle delayed payments for the Payment Add-On.
+ - AF: Added support for formatting inputs as currency.
+ - AF: Fixed notice thrown in the process_callback_action function when logging for the Payment Add-On.
+ - AF: Updated maybe_process_feeds function to not process feeds set as inactive.
+ - AF: Added register and init_addons() function to allow for aid in initializing addons and support overriding them.
+ - AF: Updated process_capture function in the Payment Add-on to call complete_payment.
+ - AF: Updated Payment AF validation to only validate if the validation result is valid.
+ - AF: Fixed misspelling on database key in create table for ...gf_addon_payment_transaction for the Payment Add-On.
+ - AF: Updated confirmation function to set the transaction type on the entry for payment gateways that redirect to a url for the Payment Add-On.
+ - AF: Added code to update the payment_gateway meta for the entry when the gateway is a URL redirect for the Payment Add-On.
+ - AF: Fixed notices thrown in the complete_payment function in the Payment Add-On.
+ - AF: Updated priority of Payment AF validation from 10 to 20 to ensure all validation has passed before payment validation occurs (resolves issue where validation could sometimes fail AFTER a subscription was created).
+ - AF: Fixed issue where "name" attribute was output twice.
+ - AF: Updated 'name' property of plugin settings tabs to use slug rather than short title.
+ - AF: Fixed issue where feed status was not saved.
+ - AF: Added a post_callback function to the Payment Add-On.
+ - AF: Added tooltips to the Payment Add-On.
+
-------------------------------------------------------------------------------------------------------------------
Version 1.8.9
- Added "password" to the list of fields which allow HTML input.
diff --git a/common.php b/common.php
index ce5aea1..70a630a 100644
--- a/common.php
+++ b/common.php
@@ -220,13 +220,31 @@ public static function is_invalid_or_empty_email($email){
return empty($email) || !self::is_valid_email($email);
}
- public static function is_valid_url($url){
- return preg_match('!^(http|https)://([\w-]+\.?)+[\w-]+(:\d+)?(/[\w- ./?~%&=+\']*)?$!', $url);
- }
+ public static function is_valid_url( $url ) {
+ $url = trim( $url );
- public static function is_valid_email($email){
- return preg_match('/^(([a-zA-Z0-9_.\-+!#$&\'*+=?^`{|}~])+\@((([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+|localhost) *,? *)+$/', $email);
- }
+ return ( ( strpos( $url, 'http://' ) === 0 || strpos( $url, 'https://' ) === 0 ) &&
+ filter_var( $url, FILTER_VALIDATE_URL ) !== false );
+ }
+
+ public static function is_valid_email( $email ) {
+ return filter_var( $email, FILTER_VALIDATE_EMAIL );
+ }
+
+ public static function is_valid_email_list( $email_list ) {
+ $emails = explode( ',', $email_list );
+ if ( ! is_array( $emails ) ){
+ return false;
+ }
+
+ foreach( $emails as $email ){
+ if ( ! filter_var( $email, FILTER_VALIDATE_EMAIL ) ) {
+ return false;
+ }
+ }
+
+ return true;
+ }
public static function get_label($field, $input_id = 0, $input_only = false){
return RGFormsModel::get_label($field, $input_id, $input_only);
@@ -694,17 +712,25 @@ public static function replace_variables($text, $form, $lead, $url_encode = fals
case "fileupload" :
if(rgar($field, "multipleFiles")){
- $files = empty($value) ? array() : json_decode($value, true);
- foreach($files as &$file){
- $file = str_replace(" ", "%20", $file);
- }
- $value = join("\r\n", $files);
- if($format == "html"){
- $value = nl2br($value);
- }
- } else {
- $value = str_replace(" ", "%20", $value);
- }
+
+ $files = empty( $raw_value ) ? array() : json_decode( $raw_value, true );
+ foreach ( $files as &$file ) {
+
+ $file = str_replace( ' ', '%20', $file );
+
+ if ( $esc_html ){
+ $value = esc_html( $value );
+ }
+ }
+ $value = $format == 'html' ? join( " ", $files ) : join( ", ", $files );
+
+ } else {
+ $value = str_replace( ' ', '%20', $value );
+ }
+
+ if ( $url_encode ){
+ $value = urlencode( $value );
+ }
break;
@@ -872,14 +898,14 @@ public static function replace_variables($text, $form, $lead, $url_encode = fals
$text = str_replace("{entry_url}", $url_encode ? urlencode($entry_url) : $entry_url, $text);
//post id
- $text = str_replace("{post_id}", $url_encode ? urlencode($lead["post_id"]) : $lead["post_id"], $text);
+ $text = str_replace("{post_id}", $url_encode ? urlencode(rgar($lead, "post_id")) : rgar($lead, "post_id"), $text);
//admin email
$wp_email = get_bloginfo("admin_email");
$text = str_replace("{admin_email}", $url_encode ? urlencode($wp_email) : $wp_email, $text);
//post edit url
- $post_url = get_bloginfo("wpurl") . "/wp-admin/post.php?action=edit&post=" . $lead["post_id"];
+ $post_url = get_bloginfo("wpurl") . "/wp-admin/post.php?action=edit&post=" . rgar($lead, "post_id");
$text = str_replace("{post_edit_url}", $url_encode ? urlencode($post_url) : $post_url, $text);
$text = self::replace_variables_prepopulate($text, $url_encode);
@@ -1282,7 +1308,10 @@ private static function prepare_user_notification($form, $lead, $override_option
$message_format = apply_filters("gform_notification_format_{$form["id"]}", apply_filters("gform_notification_format", "html", "user", $form, $lead), "user", $form, $lead);
$message = GFCommon::replace_variables(rgget("message", $form["autoResponder"]), $form, $lead, false, false, !rgget("disableAutoformat", $form["autoResponder"]), $message_format);
- $message = do_shortcode($message);
+
+ if(apply_filters("gform_enable_shortcode_notification_message", true, $form, $lead)){
+ $message = do_shortcode($message);
+ }
//Running trough variable replacement
$to = GFCommon::replace_variables($to, $form, $lead, false, false);
@@ -1314,7 +1343,10 @@ private static function prepare_admin_notification($form, $lead, $override_optio
$message_format = apply_filters("gform_notification_format_{$form["id"]}", apply_filters("gform_notification_format", "html", "admin", $form, $lead), "admin", $form, $lead);
$message = GFCommon::replace_variables(rgget("message", $form["notification"]), $form, $lead, false, false, !rgget("disableAutoformat", $form["notification"]), $message_format);
- $message = do_shortcode($message);
+
+ if(apply_filters("gform_enable_shortcode_notification_message", true, $form, $lead)){
+ $message = do_shortcode($message);
+ }
$version_info = self::get_version_info();
$is_expired = !rgempty("expiration_time", $version_info) && $version_info["expiration_time"] < time();
@@ -1344,7 +1376,7 @@ private static function prepare_admin_notification($form, $lead, $override_optio
$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) && !RGFormsModel::is_field_hidden($form, $source_field, array(), $lead);
+ $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"];
@@ -1399,7 +1431,7 @@ public static function send_notification($notification, $form, $lead){
$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) && !RGFormsModel::is_field_hidden($form, $source_field, array(), $lead);
+ $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"];
@@ -1422,7 +1454,10 @@ public static function send_notification($notification, $form, $lead){
$message_format = rgempty("message_format", $notification) ? "html" : rgar($notification, "message_format");
$message = GFCommon::replace_variables(rgar($notification, "message"), $form, $lead, false, false, !rgar($notification, "disableAutoformat"), $message_format);
- $message = do_shortcode($message);
+
+ 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" );
@@ -1559,28 +1594,30 @@ public static function has_user_notification($form){
private static function send_email($from, $to, $bcc, $reply_to, $subject, $message, $from_name="", $message_format="html", $attachments=""){
- $to = str_replace(" ", "", $to);
- $bcc = str_replace(" ", "", $bcc);
+ $to = str_replace( " ", "", $to );
+ $bcc = str_replace( " ", "", $bcc );
+ $error = false;
- //invalid to email address or no content. can't send email
- if(!GFCommon::is_valid_email($to) || (empty($subject) && empty($message))){
- GFCommon::log_debug("Cannot send email because either the TO address is invalid or there is no SUBJECT or MESSAGE.");
- GFCommon::log_debug(print_r(compact("to", "subject", "message"), true));
- return;
- }
+ if( ! GFCommon::is_valid_email( $from ) ) {
+ $from = get_bloginfo( 'admin_email' );
+ }
- if(!GFCommon::is_valid_email($from))
- $from = get_bloginfo("admin_email");
+ if( ! GFCommon::is_valid_email_list( $to ) ) {
+ $error = new WP_Error( 'invalid_to', 'Cannot send email because the TO address is invalid.' );
+ } else if( empty( $subject ) && empty( $message ) ) {
+ $error = new WP_Error( 'missing_subject_and_message', 'Cannot send email because there is no SUBJECT and no MESSAGE.' );
+ } else if( ! GFCommon::is_valid_email( $from ) ) {
+ $error = new WP_Error( 'invalid_from', 'Cannot send email because the FROM address is invalid.' );
+ }
- //invalid from address. can't send email
- if(!GFCommon::is_valid_email($from)){
- GFCommon::log_debug("Cannot send email because the FROM address is invalid.");
- GFCommon::log_debug(print_r(compact("to", "from", "subject"), true));
+ if( is_wp_error( $error ) ) {
+ GFCommon::log_debug( $error->get_error_message() );
+ GFCommon::log_debug( print_r( compact( 'to', 'subject', 'message' ), true ) );
+ do_action( 'gform_send_email_failed', $error, compact( 'from', 'to', 'bcc', 'reply_to', 'subject', 'message', 'from_name', 'message_format', 'attachments' ) );
return;
- }
+ }
$content_type = $message_format == "html" ? "text/html" : "text/plain";
-
$name = empty($from_name) ? $from : $from_name;
$headers = array();
@@ -1589,7 +1626,7 @@ private static function send_email($from, $to, $bcc, $reply_to, $subject, $messa
if(GFCommon::is_valid_email($reply_to))
$headers["Reply-To"] = "Reply-To: {$reply_to}";
- if(GFCommon::is_valid_email($bcc))
+ if(GFCommon::is_valid_email_list($bcc))
$headers["Bcc"] = "Bcc: $bcc";
$headers["Content-type"] = "Content-type: {$content_type}; charset=" . get_option('blog_charset');
@@ -1801,15 +1838,16 @@ public static function get_version_info($cache=true){
$options['timeout'] = 15;
$nocache = $cache ? "" : "nocache=1"; //disabling server side caching
-
+
$raw_response = self::post_to_manager("version.php", $nocache, $options);
//caching responses.
set_transient("gform_update_info", $raw_response, 86400); //caching for 24 hours
}
- if ( is_wp_error( $raw_response ) || $raw_response['response']['code'] != 200 )
+ if ( is_wp_error( $raw_response ) || rgars($raw_response, 'response/code') != 200 ) {
return array("is_valid_key" => "1", "version" => "", "url" => "", "is_error" => "1");
+ }
$version_info = json_decode($raw_response['body'], true);
@@ -1994,9 +2032,14 @@ public static function selection_display($value, $field, $currency="", $use_text
return "";
}
- $ary = explode("|", $value);
- $val = $ary[0];
- $price = count($ary) > 1 ? $ary[1] : "";
+ if ( isset( $field['enablePrice'] ) && $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);
@@ -2350,31 +2393,48 @@ public static function get_select_choices($field, $value=""){
return $choices;
}
- public static function is_section_empty($section_field, $form, $lead){
- $cache_key = "GFCommon::is_section_empty_" . $form["id"] . "_" . $section_field["id"];
+ public static function is_section_empty( $section_field, $form, $entry ) {
- $value = GFCache::get($cache_key);
+ $cache_key = "GFCommon::is_section_empty_{$form['id']}_{$section_field['id']}";
+ $value = GFCache::get( $cache_key );
- if($value !== 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);
+ $fields = self::get_section_fields( $form, $section_field['id'] );
+ if( ! is_array( $fields ) ) {
+ GFCache::set( $cache_key, 1 );
return true;
}
- foreach($fields as $field){
- $val = RGFormsModel::get_lead_field_value($lead, $field);
- $val = GFCommon::get_lead_field_display($field, $val, rgar($lead, 'currency'));
+ 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;
- if(!self::is_product_field($field["type"]) && !rgblank($val)){
- GFCache::set($cache_key, 0);
+ // 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'] ) ) {
+ $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);
+ GFCache::set( $cache_key, 1 );
return true;
}
@@ -3861,21 +3921,21 @@ public static function get_field_input($field, $value="", $lead_id=0, $form_id=0
$has_columns = is_array(rgar($field, "choices"));
$columns = $has_columns ? rgar($field, "choices") : array(array());
+ $label_target_shim = sprintf( '', $form_id, $field['id'] );
$list = "
" . __("Select which field determines the recurring payment amount, or select 'Form Total' to use the total of all pricing fields as the recurring amount.", "gravityforms")
),
array(
"name" => "billingCycle",
"label" => __("Billing Cycle", "gravityforms"),
"type" => "billing_cycle",
+ "tooltip" => "
" . __("Billing Cycle", "gravityforms") . "
" . __("Select your billing cycle. This determines how often the recurring payment should occur.", "gravityforms")
),
array(
"name" => "recurringTimes",
"label" => __("Recurring Times", "gravityforms"),
"type" => "select",
- "choices" => array(array("label" => "infinite", "value" => "0")) + $this->get_numeric_choices(1,100)
+ "choices" => array(array("label" => "infinite", "value" => "0")) + $this->get_numeric_choices(1,100),
+ "tooltip" => "
" . __("Recurring Times", "gravityforms") . "
" . __("Select how many times the recurring payment should be made. The default is to bill the customer until the subscription is canceled.", "gravityforms")
),
array(
"name" => "setupFee",
@@ -1113,7 +1192,8 @@ public function feed_settings_fields() {
"name" => "trial",
"label" => __("Trial", "gravityforms"),
"type" => "trial",
- "hidden" => $this->get_setting("setupFee_enabled")
+ "hidden" => $this->get_setting("setupFee_enabled"),
+ "tooltip" => "
" . __("Trial Period", "gravityformspaypal") . "
" . __("Enable a trial period. The users recurring payment will not begin until after this trial period.", "gravityforms")
)
)
),
@@ -1131,7 +1211,8 @@ public function feed_settings_fields() {
"type" => "select",
"choices" => $this->product_amount_choices(),
"required" => true,
- "default_value" => "form_total"
+ "default_value" => "form_total",
+ "tooltip" => "
" . __("Payment Amount", "gravityforms") . "
" . __("Select which field determines the payment amount, or select 'Form Total' to use the total of all pricing fields as the payment amount.", "gravityforms")
)
)
),
@@ -1154,7 +1235,8 @@ public function other_settings_fields(){
"name" => "billingInformation",
"label" => __("Billing Information", "gravityforms"),
"type" => "field_map",
- "field_map" => $this->billing_info_fields()
+ "field_map" => $this->billing_info_fields(),
+ "tooltip" => "
" . __("Billing Information", "gravityforms") . "
" . __("Map your Form Fields to the available listed fields.", "gravityforms")
)
);
@@ -1171,7 +1253,8 @@ public function other_settings_fields(){
$other_settings[] = array(
"name" => "conditionalLogic",
"label" => __("Conditional Logic", "gravityforms"),
- "type" => "feed_condition"
+ "type" => "feed_condition",
+ "tooltip" => "
" . __("Conditional Logic", "gravityforms") . "
" . __("When conditions are enabled, form submissions will only be sent to the payment gateway when the conditions are met. When disabled, all form submissions will be sent to the payment gateway.", "gravityforms")
);
return $other_settings;
@@ -1253,7 +1336,7 @@ public function settings_setup_fee( $field, $echo = true ) {
public function set_trial_onchange($field){
- return "alert('firing onchange');if(jQuery(this).prop('checked')){jQuery('#{$field["name"]}_product').show('slow');if (jQuery('#{$field["name"]}_product').val() == 'enter_amount'){jQuery('#{$field["name"]}_amount').show('slow');}} else {jQuery('#{$field["name"]}_product').hide('slow');jQuery('#{$field["name"]}_amount').hide('slow');}";
+ return "if(jQuery(this).prop('checked')){jQuery('#{$field["name"]}_product').show('slow');if (jQuery('#{$field["name"]}_product').val() == 'enter_amount'){jQuery('#{$field["name"]}_amount').show();}} else {jQuery('#{$field["name"]}_product').hide('slow');jQuery('#{$field["name"]}_amount').hide();}";
}
@@ -1282,7 +1365,7 @@ public function settings_trial( $field, $echo = true ) {
"name" => $field["name"] . "_product",
"type" => "select",
"class" => $this->get_setting("{$field["name"]}_enabled") ? "" : "hidden",
- "onchange" => "if(jQuery(this).val() == 'enter_amount'){jQuery('#{$field["name"]}_amount').show('slow');} else {jQuery('#{$field["name"]}_amount').hide('slow');}",
+ "onchange" => "if(jQuery(this).val() == 'enter_amount'){jQuery('#{$field["name"]}_amount').show();} else {jQuery('#{$field["name"]}_amount').hide();}",
"choices" => $payment_choices
);
@@ -1292,7 +1375,7 @@ public function settings_trial( $field, $echo = true ) {
$amount_field = array(
"type" => "text",
"name" => "{$field["name"]}_amount",
- "class" => $this->get_setting("{$field["name"]}_enabled") && $this->get_setting("{$field["name"]}_product") == "enter_amount" ? "" : "hidden",
+ "class" => $this->get_setting("{$field["name"]}_enabled") && $this->get_setting("{$field["name"]}_product") == 'enter_amount' ? 'gform_currency' : 'hidden gform_currency',
);
$html .= " " . $this->settings_text($amount_field, false);
@@ -1381,16 +1464,13 @@ protected function get_payment_choices($form){
//--------- Stats Page -------------------
public function get_results_page_config() {
- $current_form = $this->get_current_form();
-
- if(!$this->has_feed($current_form["id"]))
- return false;
return array(
"title" => "Sales",
"search_title" => "Filter",
"capabilities" => array("gravityforms_view_entries"),
"callbacks" => array(
+ "fields" => array($this, "results_fields"),
"data" => array($this, "results_data"),
"markup" => array($this, "results_markup"),
"filter_ui" => array($this, "results_filter_ui")
@@ -1399,6 +1479,17 @@ public function get_results_page_config() {
}
+ public function results_fields($form) {
+
+ if( $this->has_feed( $form['id'] ) ){
+ return $form['fields'];
+ }
+ else {
+ return false;
+ }
+
+ }
+
public function results_markup($html, $data, $form, $fields){
$html = "
@@ -1685,8 +1776,7 @@ protected function get_sales_summary($form_id){
$tz_offset = $this->get_mysql_tz_offset();
- $summary = $wpdb->get_results(
- $wpdb->prepare("
+ $sql = $wpdb->prepare("
SELECT lead.date, lead.orders, lead.subscriptions, transaction.revenue
FROM (
SELECT date( CONVERT_TZ(date_created, '+00:00', '" . $tz_offset . "') ) as date,
@@ -1705,7 +1795,9 @@ protected function get_sales_summary($form_id){
WHERE l.form_id=%d
GROUP BY date
) AS transaction on lead.date = transaction.date
- ORDER BY date desc", $form_id, $form_id), ARRAY_A);
+ ORDER BY date desc", $form_id, $form_id);
+
+ $summary = $wpdb->get_results($sql, ARRAY_A);
$total_summary = $wpdb->get_results(
$wpdb->prepare("
@@ -1743,7 +1835,7 @@ protected function get_sales_summary($form_id){
$result["yesterday"]["subscriptions"] = $day["subscriptions"];
}
- $is_within_30_days = strtotime($day["date"]) >= strtotime($local_time . " -30 days") ;
+ $is_within_30_days = strtotime( $day["date"] ) >= strtotime( "-30 days", $local_time ) ;
if($is_within_30_days){
$result["last30"]["revenue"] += floatval($day["revenue"]);
$result["last30"]["orders"] += floatval($day["orders"]);
@@ -1798,8 +1890,16 @@ protected function get_payment_methods($form_id){
$payment_methods = $wpdb->get_col($wpdb->prepare("SELECT DISTINCT payment_method FROM {$wpdb->prefix}rg_lead WHERE form_id=%d", $form_id));
- return $payment_methods;
+ return array_filter( $payment_methods, array( $this, 'array_filter_non_blank' ) );
}
+
+ protected function array_filter_non_blank ( $value ){
+ if( empty( $value ) || $value == 'null' ){
+ return false;
+ }
+ return true;
+ }
+
//-------- Uninstall ---------------------
protected function uninstall(){
global $wpdb;
@@ -1808,8 +1908,12 @@ protected function uninstall(){
$sql = $wpdb->prepare( "DELETE FROM {$wpdb->prefix}gf_addon_payment_transaction
WHERE lead_id IN
(SELECT lead_id FROM {$wpdb->prefix}rg_lead_meta WHERE meta_key='payment_gateway' AND meta_value=%s)", $this->_slug);
+ $wpdb->query($sql);
- $wpdb->query($sql);
+ $sql = $wpdb->prepare( "DELETE FROM {$wpdb->prefix}gf_addon_payment_callback WHERE addon_slug=%s", $this->_slug);
+ $wpdb->query($sql);
+
+ delete_option( 'gravityformsaddon_payment_version' );
//clear cron
wp_clear_scheduled_hook($this->_slug . "_cron");
@@ -1835,7 +1939,13 @@ public function scripts() {
array( "admin_page" => array( "form_settings" ), "tab" => $this->_slug ),
array( "admin_page" => array( "entry_view" ) )
)
- )
+ ),
+ array(
+ 'handle' => 'gform_form_admin',
+ 'enqueue' => array(
+ array( 'admin_page' => array( 'entry_edit' ) ),
+ ),
+ ),
);
return array_merge( parent::scripts(), $scripts );
diff --git a/includes/api.php b/includes/api.php
index 7b30465..0dbc96d 100644
--- a/includes/api.php
+++ b/includes/api.php
@@ -47,6 +47,33 @@ public static function get_form($form_id) {
}
+ /**
+ * Returns all the form objects
+ *
+ * @since 1.8.11.5
+ * @access public
+ * @static
+ *
+ * @param bool $active
+ * @param bool $trash
+ *
+ * @return mixed The array of Forms
+ */
+ public static function get_forms( $active = true, $trash = false ) {
+
+ $form_ids = GFFormsModel::get_form_ids( $active, $trash );
+ if ( empty( $form_ids ) ) {
+ return array();
+ }
+
+ $forms = array();
+ foreach ( $form_ids as $form_id ) {
+ $forms[] = GFAPI::get_form( $form_id );
+ }
+
+ return $forms;
+ }
+
/**
* Deletes the forms with the given Form IDs
*
diff --git a/includes/upload.php b/includes/upload.php
index 8a41edd..e4ef18d 100644
--- a/includes/upload.php
+++ b/includes/upload.php
@@ -36,6 +36,10 @@ public static function upload() {
$form_unique_id = rgpost("gform_unique_id");
$form = GFFormsModel::get_form_meta($form_id);
+ if ( empty( $form ) ) {
+ die();
+ }
+
$target_dir = GFFormsModel::get_upload_path($form_id) . DIRECTORY_SEPARATOR . "tmp" . DIRECTORY_SEPARATOR;
wp_mkdir_p($target_dir);
@@ -50,6 +54,11 @@ public static function upload() {
$file_name = isset($_REQUEST["name"]) ? $_REQUEST["name"] : '';
$field_id = rgpost("field_id");
$field = GFFormsModel::get_field($form, $field_id);
+
+ if ( empty( $field ) ) {
+ die();
+ }
+
// Clean the fileName for security reasons
$file_name = preg_replace('/[^\w\._]+/', '_', $file_name);
@@ -154,6 +163,11 @@ public static function upload() {
$uploaded_filename = $_FILES["file"]["name"];
+ if ( file_exists( $file_path ) ) {
+ GFFormsModel::set_permissions( $file_path );
+ } else {
+ die( '{"status" : "error", "error" : {"code": 105, "message": "' . __( 'Upload unsuccessful:', 'gravityforms' ) . ' '. $uploaded_filename . '"}}' );
+ }
$output = array("status" => "ok",
"data" => array("temp_filename" => $tmp_file_name ,
diff --git a/includes/webapi/webapi.php b/includes/webapi/webapi.php
index fdd7704..8b7bf27 100644
--- a/includes/webapi/webapi.php
+++ b/includes/webapi/webapi.php
@@ -1080,7 +1080,7 @@ public function results_cache_exists($form_id) {
$key = $this->get_results_cache_key_prefix($form_id);
- $key = "%" . like_escape($key) . "%";
+ $key = "%" . GFCommon::esc_like( $key ) . "%";
$sql = $wpdb->prepare("SELECT count(option_id) FROM $wpdb->options WHERE option_name LIKE %s", $key);
@@ -1099,7 +1099,7 @@ public function delete_cached_results($form_id) {
$key = $this->get_results_cache_key_prefix($form_id);
- $key = "%" . like_escape($key) . "%";
+ $key = "%" . GFCommon::esc_like( $key ) . "%";
$sql = $wpdb->prepare("DELETE FROM $wpdb->options WHERE option_name LIKE %s", $key);
diff --git a/js/chosen.jquery.min.js b/js/chosen.jquery.min.js
index 1215390..cece231 100644
--- a/js/chosen.jquery.min.js
+++ b/js/chosen.jquery.min.js
@@ -1,10 +1,2 @@
-// Chosen, a Select Box Enhancer for jQuery and Protoype
-// by Patrick Filler for Harvest, http://getharvest.com
-//
-// Version 0.9.12
-// Full source at https://github.com/harvesthq/chosen
-// Copyright (c) 2011 Harvest http://getharvest.com
-
-// MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md
-// This file is generated by `cake build`, do not edit it by hand.
-(function(){var e;e=function(){function e(){this.options_index=0,this.parsed=[]}return e.prototype.add_node=function(e){return e.nodeName.toUpperCase()==="OPTGROUP"?this.add_group(e):this.add_option(e)},e.prototype.add_group=function(e){var t,n,r,i,s,o;t=this.parsed.length,this.parsed.push({array_index:t,group:!0,label:e.label,children:0,disabled:e.disabled}),s=e.childNodes,o=[];for(r=0,i=s.length;r"+e.html+"")},e.prototype.results_update_field=function(){return this.is_multiple||this.results_reset_cleanup(),this.result_clear_highlight(),this.result_single_selected=null,this.results_build()},e.prototype.results_toggle=function(){return this.results_showing?this.results_hide():this.results_show()},e.prototype.results_search=function(e){return this.results_showing?this.winnow_results():this.results_show()},e.prototype.keyup_checker=function(e){var t,n;t=(n=e.which)!=null?n:e.keyCode,this.search_field_scale();switch(t){case 8:if(this.is_multiple&&this.backstroke_length<1&&this.choices>0)return this.keydown_backstroke();if(!this.pending_backstroke)return this.result_clear_highlight(),this.results_search();break;case 13:e.preventDefault();if(this.results_showing)return this.result_select(e);break;case 27:return this.results_showing&&this.results_hide(),!0;case 9:case 38:case 40:case 16:case 91:case 17:break;default:return this.results_search()}},e.prototype.generate_field_id=function(){var e;return e=this.generate_random_id(),this.form_field.id=e,e},e.prototype.generate_random_char=function(){var e,t,n;return e="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ",n=Math.floor(Math.random()*e.length),t=e.substring(n,n+1)},e}(),t.AbstractChosen=e}.call(this),function(){var e,t,n,r,i={}.hasOwnProperty,s=function(e,t){function r(){this.constructor=e}for(var n in t)i.call(t,n)&&(e[n]=t[n]);return r.prototype=t.prototype,e.prototype=new r,e.__super__=t.prototype,e};r=this,e=jQuery,e.fn.extend({chosen:function(n){var r,i,s;return s=navigator.userAgent.toLowerCase(),i=/(msie) ([\w.]+)/.exec(s)||[],r={name:i[1]||"",version:i[2]||"0"},r.name==="msie"&&(r.version==="6.0"||r.version==="7.0"&&document.documentMode===7)?this:this.each(function(r){var i;i=e(this);if(!i.hasClass("chzn-done"))return i.data("chosen",new t(this,n))})}}),t=function(t){function i(){return i.__super__.constructor.apply(this,arguments)}return s(i,t),i.prototype.setup=function(){return this.form_field_jq=e(this.form_field),this.current_value=this.form_field_jq.val(),this.is_rtl=this.form_field_jq.hasClass("chzn-rtl")},i.prototype.finish_setup=function(){return this.form_field_jq.addClass("chzn-done")},i.prototype.set_up_html=function(){var t,r,i,s,o,u;return this.container_id=this.form_field.id.length?this.form_field.id.replace(/[^\w]/g,"_"):this.generate_field_id(),this.container_id+="_chzn",t=["chzn-container"],t.push("chzn-container-"+(this.is_multiple?"multi":"single")),this.inherit_select_classes&&this.form_field.className&&t.push(this.form_field.className),this.is_rtl&&t.push("chzn-rtl"),this.f_width=this.form_field_jq.outerWidth(),i={id:this.container_id,"class":t.join(" "),style:"width: "+this.f_width+"px;",title:this.form_field.title},r=e("",i),this.is_multiple?r.html('