_slug}", array( $this, 'ajax_toggle_is_active' ) ); add_action( 'wp_ajax_gf_save_feed_order', array( $this, 'ajax_save_feed_order' ) ); } /** * Override this function to add initialization code (i.e. hooks) for the admin site (WP dashboard) */ public function init_admin() { parent::init_admin(); add_filter( 'gform_notification_events', array( $this, 'notification_events' ), 10, 2 ); add_filter( 'gform_notes_avatar', array( $this, 'notes_avatar' ), 10, 2 ); add_action( 'gform_post_form_duplicated', array( $this, 'post_form_duplicated' ), 10, 2 ); } /** * Performs upgrade tasks when the version of the Add-On changes. To add additional upgrade tasks, override the upgrade() function, which will only get executed when the plugin version has changed. */ public function setup() { // upgrading Feed Add-On base class $installed_version = get_option( 'gravityformsaddon_feed-base_version' ); if ( $installed_version != $this->_feed_version ) { $this->upgrade_base( $installed_version ); update_option( 'gravityformsaddon_feed-base_version', $this->_feed_version ); } parent::setup(); } private function upgrade_base( $previous_version ) { global $wpdb; require_once( ABSPATH . '/wp-admin/includes/upgrade.php' ); if ( ! empty( $wpdb->charset ) ) { $charset_collate = "DEFAULT CHARACTER SET $wpdb->charset"; } if ( ! empty( $wpdb->collate ) ) { $charset_collate .= " COLLATE $wpdb->collate"; } $sql = "CREATE TABLE {$wpdb->prefix}gf_addon_feed ( id mediumint(8) unsigned not null auto_increment, form_id mediumint(8) unsigned not null, is_active tinyint(1) not null default 1, feed_order mediumint(8) unsigned not null default 0, meta longtext, addon_slug varchar(50), event_type varchar(20), PRIMARY KEY (id), KEY addon_form (addon_slug,form_id) ) $charset_collate;"; gf_upgrade()->dbDelta( $sql ); } /** * Gets called when Gravity Forms upgrade process is completed. This function is intended to be used internally, override the upgrade() function to execute database update scripts. * @param $db_version - Current Gravity Forms database version * @param $previous_db_version - Previous Gravity Forms database version * @param $force_upgrade - True if this is a request to force an upgrade. False if this is a standard upgrade (due to version change) */ public function post_gravityforms_upgrade( $db_version, $previous_db_version, $force_upgrade ) { // Forcing Upgrade if ( $force_upgrade ) { $installed_version = get_option( 'gravityformsaddon_feed-base_version' ); $this->upgrade_base( $installed_version ); update_option( 'gravityformsaddon_feed-base_version', $this->_feed_version ); } parent::post_gravityforms_upgrade( $db_version, $previous_db_version, $force_upgrade ); } public function scripts() { $min = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG || isset( $_GET['gform_debug'] ) ? '' : '.min'; $scripts = array( array( 'handle' => 'gform_form_admin', 'enqueue' => array( array( 'admin_page' => array( 'form_settings' ) ) ), ), array( 'handle' => 'gform_gravityforms', 'enqueue' => array( array( 'admin_page' => array( 'form_settings' ) ) ), ), array( 'handle' => 'gform_forms', 'enqueue' => array( array( 'admin_page' => array( 'form_settings' ) ) ), ), array( 'handle' => 'json2', 'enqueue' => array( array( 'admin_page' => array( 'form_settings' ) ) ), ), array( 'handle' => 'gform_placeholder', 'enqueue' => array( array( 'admin_page' => array( 'form_settings' ), 'field_types' => array( 'feed_condition' ), ), ) ), ); if ( $this->_supports_feed_ordering ) { $scripts[] = array( 'handle' => 'gaddon_feedorder', 'src' => $this->get_gfaddon_base_url() . "/js/gaddon_feedorder{$min}.js", 'version' => GFCommon::$version, 'deps' => array( 'jquery', 'jquery-ui-sortable' ), 'in_footer' => false, 'enqueue' => array( array( 'admin_page' => array( 'form_settings' ) ), ), ); } return array_merge( parent::scripts(), $scripts ); } public function uninstall() { global $wpdb; $sql = $wpdb->prepare( "DELETE FROM {$wpdb->prefix}gf_addon_feed WHERE addon_slug=%s", $this->_slug ); $wpdb->query( $sql ); } //-------- Front-end methods --------------------------- /** * Determines what feeds need to be processed for the provided entry. * * @access public * @param array $entry The Entry Object currently being processed. * @param array $form The Form Object currently being processed. * * @return array $entry */ public function maybe_process_feed( $entry, $form ) { if ( 'spam' === $entry['status'] ) { $this->log_debug( "GFFeedAddOn::maybe_process_feed(): Entry #{$entry['id']} is marked as spam; not processing feeds for {$this->_slug}." ); return $entry; } $this->log_debug( __METHOD__ . "(): Checking for feeds to process for entry #{$entry['id']} for {$this->_slug}." ); $feeds = false; // If this is a single submission feed, get the first feed. Otherwise, get all feeds. if ( $this->_single_feed_submission ) { $feed = $this->get_single_submission_feed( $entry, $form ); if ( $feed ) { $feeds = array( $feed ); } } else { $feeds = $this->get_feeds( $form['id'] ); } // Run filters before processing feeds. $feeds = $this->pre_process_feeds( $feeds, $entry, $form ); // If there are no feeds to process, return. if ( empty( $feeds ) ) { $this->log_debug( __METHOD__ . "(): No feeds to process for entry #{$entry['id']}." ); return $entry; } // Determine if feed processing needs to be delayed. $is_delayed = $this->maybe_delay_feed( $entry, $form ); // Initialize array of feeds that have been processed. $processed_feeds = array(); // Loop through feeds. foreach ( $feeds as $feed ) { // Get the feed name. $feed_name = rgempty( 'feed_name', $feed['meta'] ) ? rgar( $feed['meta'], 'feedName' ) : rgar( $feed['meta'], 'feed_name' ); // If this feed is inactive, log that it's not being processed and skip it. if ( ! $feed['is_active'] ) { $this->log_debug( "GFFeedAddOn::maybe_process_feed(): Feed is inactive, not processing feed (#{$feed['id']} - {$feed_name}) for entry #{$entry['id']}." ); continue; } // If this feed's condition is not met, log that it's not being processed and skip it. if ( ! $this->is_feed_condition_met( $feed, $form, $entry ) ) { $this->log_debug( "GFFeedAddOn::maybe_process_feed(): Feed condition not met, not processing feed (#{$feed['id']} - {$feed_name}) for entry #{$entry['id']}." ); continue; } // process feed if not delayed if ( ! $is_delayed ) { // If asynchronous feed processing is enabled, add it to the processing queue. if ( $this->is_asynchronous( $feed, $entry, $form ) ) { // Log that feed processing is being delayed. $this->log_debug( "GFFeedAddOn::maybe_process_feed(): Adding feed (#{$feed['id']} - {$feed_name}) for entry #{$entry['id']} for {$this->_slug} to the processing queue." ); // Add feed to processing queue. gf_feed_processor()->push_to_queue( array( 'addon' => $this, 'feed' => $feed, 'entry_id' => $entry['id'], 'form_id' => $form['id'], ) ); } else { // All requirements are met; process feed. $this->log_debug( "GFFeedAddOn::maybe_process_feed(): Starting to process feed (#{$feed['id']} - {$feed_name}) for entry #{$entry['id']} for {$this->_slug}" ); $returned_entry = $this->process_feed( $feed, $entry, $form ); // If returned value from the process feed call is an array containing an id, set the entry to its value. if ( is_array( $returned_entry ) && rgar( $returned_entry, 'id' ) ) { $entry = $returned_entry; } /** * Perform a custom action when a feed has been processed. * * @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). * * @since 2.0 */ do_action( 'gform_post_process_feed', $feed, $entry, $form, $this ); do_action( "gform_{$this->_slug}_post_process_feed", $feed, $entry, $form, $this ); // Log that Add-On has been fulfilled. $this->log_debug( 'GFFeedAddOn::maybe_process_feed(): Marking entry #' . $entry['id'] . ' as fulfilled for ' . $this->_slug ); gform_update_meta( $entry['id'], "{$this->_slug}_is_fulfilled", true ); // Adding this feed to the list of processed feeds $processed_feeds[] = $feed['id']; } } else { // Log that feed processing is being delayed. $this->log_debug( 'GFFeedAddOn::maybe_process_feed(): Feed processing is delayed, not processing feed for entry #' . $entry['id'] . ' for ' . $this->_slug ); // Delay feed. $this->delay_feed( $feed, $entry, $form ); } } // If any feeds were processed, save the processed feed IDs. if ( ! empty( $processed_feeds ) ) { // 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 Add-On's processed feeds to the entry meta. $meta[ $this->_slug ] = $processed_feeds; // Update the entry meta. gform_update_meta( $entry['id'], 'processed_feeds', $meta ); } // Return the entry object. return $entry; } /** * Determines if feed processing is delayed by the PayPal Standard Add-On. * * Also enables use of the gform_is_delayed_pre_process_feed filter. * * @param array $entry The Entry Object currently being processed. * @param array $form The Form Object currently being processed. * * @return bool */ public function maybe_delay_feed( $entry, $form ) { if ( $this->_bypass_feed_delay ) { return false; } $is_delayed = false; $slug = $this->get_slug(); if ( $slug != 'gravityformspaypal' && class_exists( 'GFPayPal' ) && function_exists( 'gf_paypal' ) ) { if ( gf_paypal()->is_payment_gateway( $entry['id'] ) ) { $paypal_feed = gf_paypal()->get_single_submission_feed( $entry ); if ( $paypal_feed && $this->is_delayed( $paypal_feed ) ) { $is_delayed = true; } } } /** * Allow feed processing to be delayed. * * @param bool $is_delayed Is feed processing delayed? * @param array $form The Form Object currently being processed. * @param array $entry The Entry Object currently being processed. * @param string $slug The Add-On slug e.g. gravityformsmailchimp */ $is_delayed = apply_filters( 'gform_is_delayed_pre_process_feed', $is_delayed, $form, $entry, $slug ); $is_delayed = apply_filters( 'gform_is_delayed_pre_process_feed_' . $form['id'], $is_delayed, $form, $entry, $slug ); return $is_delayed; } /** * Retrieves the delay setting for the current add-on from the PayPal feed. * * @param array $paypal_feed The PayPal feed which is being used to process the current submission. * * @return bool|null */ public function is_delayed( $paypal_feed ) { $delay = rgar( $paypal_feed['meta'], 'delay_' . $this->_slug ); return $delay; } /** * Determines if feed processing should happen asynchronously. * * @since 2.2 * @access public * * @param array $feed The Feed Object currently being processed. * @param array $form The Form Object currently being processed. * @param array $entry The Entry Object currently being processed. * * @return bool */ public function is_asynchronous( $feed, $entry, $form ) { /** * Allow feed to be processed asynchronously. * * @since 2.2 * * @param bool $is_asynchronous Is feed being processed asynchronously? * @param array $feed The Feed Object currently being processed. * @param array $entry The Entry Object currently being processed. * @param array $form The Form Object currently being processed. */ $is_asynchronous = gf_apply_filters( array( 'gform_is_feed_asynchronous', $form['id'], $feed['id'] ), $this->_async_feed_processing, $feed, $entry, $form ); return $is_asynchronous; } /** * Processes feed action. * * @since Unknown * @access public * * @param array $feed The Feed Object currently being processed. * @param array $entry The Entry Object currently being processed. * @param array $form The Form Object currently being processed. * * @return array|null Returns a modified entry object or null. */ public function process_feed( $feed, $entry, $form ) { return; } public function delay_feed( $feed, $entry, $form ) { return; } public function is_feed_condition_met( $feed, $form, $entry ) { $feed_meta = $feed['meta']; $is_condition_enabled = rgar( $feed_meta, 'feed_condition_conditional_logic' ) == true; $logic = rgars( $feed_meta, 'feed_condition_conditional_logic_object/conditionalLogic' ); if ( ! $is_condition_enabled || empty( $logic ) ) { return true; } return GFCommon::evaluate_conditional_logic( $logic, $form, $entry ); } /** * Create nonce for asynchronous feed processing. * * @since 2.2 * @access public * * @return string The nonce. */ public function create_feed_nonce() { $action = 'gform_' . $this->_slug . '_process_feed'; $i = wp_nonce_tick(); return substr( wp_hash( $i . $action, 'nonce' ), - 12, 10 ); } /** * Verify nonce for asynchronous feed processing. * * @since 1.0 * @access public * @param string $nonce Nonce to be verified. * * @return int|bool */ public function verify_feed_nonce( $nonce ) { $action = 'gform_' . $this->_slug . '_process_feed'; $i = wp_nonce_tick(); // Nonce generated 0-12 hours ago. if ( substr( wp_hash( $i . $action, 'nonce' ), - 12, 10 ) === $nonce ) { return 1; } // Nonce generated 12-24 hours ago. if ( substr( wp_hash( ( $i - 1 ) . $action, 'nonce' ), - 12, 10 ) === $nonce ) { return 2; } // Log that nonce was unable to be verified. $this->log_error( __METHOD__ . '(): Aborting. Unable to verify nonce.' ); return false; } /** * Retrieves notification events supported by Add-On. * * @access public * @param array $form * @return array */ public function supported_notification_events( $form ) { return array(); } /** * Add notifications events supported by Add-On to notification events list. * * @access public * @param array $events * @param array $form * @return array $events */ public function notification_events( $events, $form ) { /* Get the supported notification events for this Add-On. */ $supported_events = $this->supported_notification_events( $form ); /* If no events are supported, return the current array of events. */ if ( empty( $supported_events ) ) { return $events; } return array_merge( $events, $supported_events ); } //-------- Feed data methods ------------------------- public function get_feeds( $form_id = null ) { global $wpdb; $form_filter = is_numeric( $form_id ) ? $wpdb->prepare( 'AND form_id=%d', absint( $form_id ) ) : ''; $sql = $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}gf_addon_feed WHERE addon_slug=%s {$form_filter} ORDER BY `feed_order`, `id` ASC", $this->_slug ); $results = $wpdb->get_results( $sql, ARRAY_A ); foreach ( $results as &$result ) { $result['meta'] = json_decode( $result['meta'], true ); } return $results; } public function get_active_feeds( $form_id = null ) { global $wpdb; $form_filter = is_numeric( $form_id ) ? $wpdb->prepare( 'AND form_id=%d', absint( $form_id ) ) : ''; $sql = $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}gf_addon_feed WHERE addon_slug=%s AND is_active=1 {$form_filter} ORDER BY `feed_order`, `id` ASC", $this->_slug ); $results = $wpdb->get_results( $sql, ARRAY_A ); foreach ( $results as &$result ) { $result['meta'] = json_decode( $result['meta'], true ); } return $results; } public function get_feeds_by_slug( $slug, $form_id = null ) { global $wpdb; $form_filter = is_numeric( $form_id ) ? $wpdb->prepare( 'AND form_id=%d', absint( $form_id ) ) : ''; $sql = $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}gf_addon_feed WHERE addon_slug=%s {$form_filter} ORDER BY `feed_order`, `id` ASC", $slug ); $results = $wpdb->get_results( $sql, ARRAY_A ); foreach( $results as &$result ) { $result['meta'] = json_decode( $result['meta'], true ); } return $results; } public function get_current_feed() { $feed_id = $this->get_current_feed_id(); return empty( $feed_id ) ? false : $this->get_feed( $feed_id ); } public function get_current_feed_id() { if ( $this->_current_feed_id ) { return $this->_current_feed_id; } elseif ( ! rgempty( 'gf_feed_id' ) ) { return rgpost( 'gf_feed_id' ); } else { return rgget( 'fid' ); } } public function get_feed( $id ) { global $wpdb; $sql = $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}gf_addon_feed WHERE id=%d", $id ); $row = $wpdb->get_row( $sql, ARRAY_A ); if ( ! $row ) { return false; } $row['meta'] = json_decode( $row['meta'], true ); return $row; } public function get_feeds_by_entry( $entry_id ) { $processed_feeds = gform_get_meta( $entry_id, 'processed_feeds' ); if ( ! $processed_feeds ) { return false; } return rgar( $processed_feeds, $this->_slug ); } public function has_feed( $form_id, $meets_conditional_logic = null ) { $feeds = $this->get_feeds( $form_id ); if ( ! $feeds ) { return false; } $has_active_feed = false; if ( $meets_conditional_logic ) { $form = GFFormsModel::get_form_meta( $form_id ); $entry = GFFormsModel::create_lead( $form ); } foreach ( $feeds as $feed ) { if ( ! $has_active_feed && $feed['is_active'] ) { $has_active_feed = true; } if ( $meets_conditional_logic && $feed['is_active'] && $this->is_feed_condition_met( $feed, $form, $entry ) ) { return true; } } return $meets_conditional_logic ? false : $has_active_feed; } public function get_single_submission_feed( $entry = false, $form = false ) { if ( ! $entry && ! $form ) { return false; } $feed = false; if ( ! empty( $this->_single_submission_feed ) && $this->_single_submission_feed['form_id'] == $form['id'] ) { $feed = $this->_single_submission_feed; } elseif ( $entry['id'] ) { $feeds = $this->get_feeds_by_entry( $entry['id'] ); if ( empty( $feeds ) ) { $feed = $this->get_single_submission_feed_by_form( $form, $entry ); } else { $feed = $this->get_feed( $feeds[0] ); } } elseif ( $form ) { $feed = $this->get_single_submission_feed_by_form( $form, $entry ); $this->_single_submission_feed = $feed; } return $feed; } /** * Return the active feed to be used when processing the current entry, evaluating conditional logic if configured. * * @param array $form The current form. * @param array|false $entry The current entry. * * @return bool|array */ public function get_single_submission_feed_by_form( $form, $entry ) { if ( $form ) { $feeds = $this->get_feeds( $form['id'] ); foreach ( $feeds as $_feed ) { if ( $_feed['is_active'] && $this->is_feed_condition_met( $_feed, $form, $entry ) ) { return $_feed; } } } return false; } public function pre_process_feeds( $feeds, $entry, $form ) { /** * Modify feeds before they are processed. * * @param array $feeds An array of $feed objects * @param array $entry Current entry for which feeds will be processed * @param array $form Current form object. * * @since 2.0 * * @return array An array of $feeds */ $feeds = apply_filters( 'gform_addon_pre_process_feeds', $feeds, $entry, $form ); $feeds = apply_filters( "gform_addon_pre_process_feeds_{$form['id']}", $feeds, $entry, $form ); $feeds = apply_filters( "gform_{$this->_slug}_pre_process_feeds", $feeds, $entry, $form ); $feeds = apply_filters( "gform_{$this->_slug}_pre_process_feeds_{$form['id']}", $feeds, $entry, $form ); return $feeds; } /** * Get default feed name. * * @since Unknown * @access public * * @return string */ public function get_default_feed_name() { /** * Query db to look for two formats that the feed name could have been auto-generated with * format from migration to add-on framework: 'Feed ' . $counter * new auto-generated format when adding new feed: $short_title . ' Feed ' . $counter */ // Set to zero unless a new number is found while checking existing feed names (will be incremented by 1 at the end). $counter_to_use = 0; // Get Add-On feeds. $feeds_to_filter = $this->get_feeds_by_slug( $this->_slug ); // If feeds were found, loop through and increase counter. if ( $feeds_to_filter ) { // Loop through feeds and look for name pattern to find what to make default feed name. foreach ( $feeds_to_filter as $check ) { // Get feed name and trim. $name = rgars( $check, 'meta/feed_name' ) ? rgars( $check, 'meta/feed_name' ) : rgars( $check, 'meta/feedName' ); $name = trim( $name ); // Prepare feed name pattern. $pattern = '/(^Feed|^' . $this->_short_title . ' Feed)\s\d+/'; // Search for feed name pattern. preg_match( $pattern,$name,$matches ); // If matches were found, increase counter. if ( $matches ) { // Number should be characters at the end after a space $last_space = strrpos( $matches[0], ' ' ); $digit = substr( $matches[0], $last_space ); // Counter in existing feed name greater, use it instead. if ( $digit >= $counter_to_use ){ $counter_to_use = $digit; } } } } // Set default feed name $value = $this->_short_title . ' Feed ' . ($counter_to_use + 1); return $value; } public function is_unique_feed_name( $name, $form_id ) { $feeds = $this->get_feeds( $form_id ); foreach ( $feeds as $feed ) { $feed_name = rgars( $feed, 'meta/feed_name' ) ? rgars( $feed, 'meta/feed_name' ) : rgars( $feed, 'meta/feedName' ); if ( strtolower( $feed_name ) === strtolower( $name ) ) { return false; } } return true; } public function update_feed_meta( $id, $meta ) { global $wpdb; $meta = json_encode( $meta ); $wpdb->update( "{$wpdb->prefix}gf_addon_feed", array( 'meta' => $meta ), array( 'id' => $id ), array( '%s' ), array( '%d' ) ); return $wpdb->rows_affected > 0; } public function update_feed_active( $id, $is_active ) { global $wpdb; $is_active = $is_active ? '1' : '0'; $wpdb->update( "{$wpdb->prefix}gf_addon_feed", array( 'is_active' => $is_active ), array( 'id' => $id ), array( '%d' ), array( '%d' ) ); return $wpdb->rows_affected > 0; } public function insert_feed( $form_id, $is_active, $meta ) { global $wpdb; $meta = json_encode( $meta ); $wpdb->insert( "{$wpdb->prefix}gf_addon_feed", array( 'addon_slug' => $this->_slug, 'form_id' => $form_id, 'is_active' => $is_active, 'meta' => $meta ), array( '%s', '%d', '%d', '%s' ) ); return $wpdb->insert_id; } public function delete_feed( $id ) { global $wpdb; $wpdb->delete( "{$wpdb->prefix}gf_addon_feed", array( 'id' => $id ), array( '%d' ) ); } public function delete_feeds( $form_id = null ) { global $wpdb; $form_filter = is_numeric( $form_id ) ? $wpdb->prepare( 'AND form_id=%d', absint( $form_id ) ) : ''; $sql = $wpdb->prepare( "SELECT id FROM {$wpdb->prefix}gf_addon_feed WHERE addon_slug=%s {$form_filter} ORDER BY `feed_order`, `id` ASC", $this->_slug ); $feed_ids = $wpdb->get_col( $sql ); if ( ! empty( $feed_ids ) ) { array_map( array( $this, 'delete_feed' ), $feed_ids ); } } /** * Duplicates the feed. * * @since 1.9.15 * @access public * * @param int|array $id The ID of the feed to be duplicated or the feed object when duplicating a form. * @param mixed $new_form_id False when using feed actions or the ID of the new form when duplicating a form. * * @uses GFFeedAddOn::can_duplicate_feed() * @uses GFFeedAddOn::get_feed() * @uses GFFeedAddOn::insert_feed() * @uses GFFeedAddOn::is_unique_feed_name() * * @return int New feed ID. */ public function duplicate_feed( $id, $new_form_id = false ) { // Get original feed. $original_feed = is_array( $id ) ? $id : $this->get_feed( $id ); // If feed doesn't exist, exit. if ( ! $original_feed || ! $this->can_duplicate_feed( $original_feed ) ) { return; } // Get feed name key. $feed_name_key = rgars( $original_feed, 'meta/feed_name' ) ? 'feed_name' : 'feedName'; // Make sure the new feed name is unique. $count = 2; $feed_name = rgars( $original_feed, 'meta/' . $feed_name_key ) . ' - ' . esc_html__( 'Copy 1', 'gravityforms' ); while ( ! $this->is_unique_feed_name( $feed_name, $original_feed['form_id'] ) ) { $feed_name = rgars( $original_feed, 'meta/' . $feed_name_key ) . ' - ' . sprintf( esc_html__( 'Copy %d', 'gravityforms' ), $count ); $count++; } // Copy the feed meta. $meta = $original_feed['meta']; $meta[ $feed_name_key ] = $feed_name; if ( ! $new_form_id ) { $new_form_id = $original_feed['form_id']; } // Create the new feed. return $this->insert_feed( $new_form_id, $original_feed['is_active'], $meta ); } /** * Maybe duplicate feeds when a form is duplicated. * * @param int $form_id The ID of the original form. * @param int $new_id The ID of the duplicate form. */ public function post_form_duplicated( $form_id, $new_id ) { $feeds = $this->get_feeds( $form_id ); if ( ! $feeds ) { return; } foreach ( $feeds as $feed ) { $this->duplicate_feed( $feed, $new_id ); } } /** * Save order of feeds. * * @since 2.0 * @access public * * @param array $feed_order Array of feed IDs in desired order. */ public function save_feed_order( $feed_order ) { global $wpdb; // Reindex feed order to start at 1 instead of 0. $feed_order = array_combine( range( 1, count( $feed_order ) ), array_values( $feed_order ) ); // Swap array keys and values. $feed_order = array_flip( $feed_order ); // Update each feed. foreach ( $feed_order as $feed_id => $position ) { $wpdb->update( $wpdb->prefix . 'gf_addon_feed', array( 'feed_order' => $position ), array( 'id' => $feed_id ), array( '%d' ), array( '%d' ) ); } } //---------- Form Settings Pages -------------------------- public function form_settings_init() { parent::form_settings_init(); } public function ajax_toggle_is_active() { $feed_id = rgpost( 'feed_id' ); $is_active = rgpost( 'is_active' ); $this->update_feed_active( $feed_id, $is_active ); die(); } public function ajax_save_feed_order() { check_ajax_referer( 'gform_feed_order', 'nonce' ); if ( ! $this->current_user_can_any( $this->_capabilities_form_settings ) ) { return; } $addon = sanitize_text_field( rgpost( 'addon' ) ); $form_id = absint( rgpost( 'form_id' ) ); $feed_order = rgpost( 'feed_order' ) ? rgpost( 'feed_order' ) : array(); $feed_order = array_map( 'absint', $feed_order ); if ( $addon == $this->_slug ) { $this->save_feed_order( $feed_order ); } } public function form_settings_sections() { return array(); } public function form_settings( $form ) { if ( ! $this->_multiple_feeds || $this->is_detail_page() ) { // feed edit page $feed_id = $this->_multiple_feeds ? $this->get_current_feed_id() : $this->get_default_feed_id( $form['id'] ); $this->feed_edit_page( $form, $feed_id ); } else { // feed list UI $this->feed_list_page( $form ); } } public function is_feed_list_page() { return ! isset( $_GET['fid'] ); } public function is_detail_page() { return ! $this->is_feed_list_page(); } public function form_settings_header() { if ( $this->is_feed_list_page() ) { $title = $this->form_settings_title(); $url = add_query_arg( array( 'fid' => 0 ) ); return $title . " " . esc_html__( 'Add New', 'gravityforms' ) . ''; } } public function form_settings_title() { return sprintf( esc_html__( '%s Feeds', 'gravityforms' ), $this->get_short_title() ); } public function feed_edit_page( $form, $feed_id ) { $title = '