entry, $form ); } } if ( isset( $data['process_callback'] ) ) { call_user_func( $data['process_callback'], $entry, $form ); } } // Delay notifications. // Determine if the feed has Gravity Form 1.7 Feed IDs. if ( $feed->has_delayed_notifications() ) { $delay_notification_ids = array(); foreach ( $feed->delay_notification_ids as $notification_id ) { if ( ! isset( $form['notifications'][ $notification_id ] ) ) { continue; } if ( isset( $form['notifications'][ $notification_id ]['event'] ) && 'form_submission' !== $form['notifications'][ $notification_id ]['event'] ) { continue; } $delay_notification_ids[] = $notification_id; } // @link https://bitbucket.org/Pronamic/gravityforms/src/42773f75ad7ad9ac9c31ce149510ff825e4aa01f/common.php?at=1.7.8#cl-1512 GFCommon::send_notifications( $delay_notification_ids, $form, $entry, true, 'form_submission' ); } if ( $feed->delay_admin_notification && Core_Util::class_method_exists( 'GFCommon', 'send_admin_notification' ) ) { // @link https://github.com/wp-premium/gravityforms/blob/1.8.9/common.php#L1265-L1270. GFCommon::send_admin_notification( $form, $entry ); } if ( $feed->delay_user_notification && Core_Util::class_method_exists( 'GFCommon', 'send_user_notification' ) ) { // @link https://github.com/wp-premium/gravityforms/blob/1.8.9/common.php#L1258-L1263. GFCommon::send_user_notification( $form, $entry ); } } // Store entry payment fulfillment in custom meta. gform_update_meta( $entry_id, 'pronamic_pay_payment_fulfilled', true ); // The Gravity Forms PayPal Add-On executes the 'gform_paypal_fulfillment' action. do_action( 'gform_ideal_fulfillment', $entry, $feed ); } /** * Maybe display the Gravity Forms confirmation. * * @return void */ public function maybe_display_confirmation() { if ( ! filter_has_var( INPUT_GET, 'pay_confirmation' ) || ! filter_has_var( INPUT_GET, '_wpnonce' ) ) { return; } $payment_id = filter_input( INPUT_GET, 'pay_confirmation', FILTER_SANITIZE_NUMBER_INT ); $nonce = filter_input( INPUT_GET, '_wpnonce', FILTER_SANITIZE_STRING ); // Verify nonce. if ( ! wp_verify_nonce( $nonce, 'gf_confirmation_payment_' . $payment_id ) ) { return; } $payment = get_pronamic_payment( $payment_id ); if ( null === $payment ) { return; } $lead_id = $payment->get_source_id(); $lead = RGFormsModel::get_lead( $lead_id ); // Return if lead does not exist. if ( ! $lead ) { return; } $confirmation = $this->get_confirmation( $lead, $payment->status ); // Display confirmation if it exists. if ( ! empty( $confirmation ) ) { if ( is_array( $confirmation ) && isset( $confirmation['redirect'] ) ) { wp_redirect( $confirmation['redirect'] ); exit; } $form = GFAPI::get_form( $lead['form_id'] ); GFFormDisplay::$submission[ $form['id'] ] = array( 'is_confirmation' => true, 'confirmation_message' => $confirmation, 'form' => $form, 'lead' => $lead, ); } } /** * Get confirmations for lead based on payment status. * * @param array $lead Lead. * @param string $payment_status Payment status. * * @return mixed */ public function get_confirmation( $lead, $payment_status = PaymentStatus::OPEN ) { $form = GFAPI::get_form( $lead['form_id'] ); $feed = FeedsDB::get_feed_by_entry_id( $lead['id'] ); $link = Links::transform_status( $payment_status ); if ( ! class_exists( 'GFFormDisplay' ) ) { require_once GFCommon::get_base_path() . '/form_display.php'; } // Use only link confirmation if set. if ( isset( $feed->links[ $link ]['confirmation_id'] ) && ! empty( $feed->links[ $link ]['confirmation_id'] ) ) { $confirmation_id = $feed->links[ $link ]['confirmation_id']; if ( isset( $form['confirmations'][ $confirmation_id ] ) ) { $form['confirmations'] = array_intersect_key( $form['confirmations'], array( $confirmation_id => true ) ); } } return GFFormDisplay::handle_confirmation( $form, $lead, false ); } /** * Replace merge tags * * @param string $text The text in which merge tags are being processed. * @param array|false $form The Form object if available or false. * @param array|false $entry The Entry object if available or false. * @param boolean $url_encode Indicates if the urlencode function should be applied. * @param boolean $esc_html Indicates if the esc_html function should be applied. * @param boolean $nl2br Indicates if the nl2br function should be applied. * @param string $format The format requested for the location the merge is being used. Possible values: html, text or url. * * @return string */ public function replace_merge_tags( $text, $form, $entry, $url_encode, $esc_html, $nl2br, $format ) { $subscription_amount = ''; $subscription_cancel_url = ''; $subscription_renew_url = ''; $subscription_renewal_date = ''; $subscription_id = gform_get_meta( rgar( $entry, 'id' ), 'pronamic_subscription_id' ); if ( ! empty( $subscription_id ) ) { $subscription = get_pronamic_subscription( $subscription_id ); $next_payment_date = $subscription->get_next_payment_date(); if ( $next_payment_date ) { $subscription_renewal_date = date_i18n( get_option( 'date_format' ), $next_payment_date->getTimestamp() ); } // Get amount from current phase. $current_phase = $subscription->get_current_phase(); $subscription_amount = null; if ( null !== $current_phase ) { $subscription_amount = $current_phase->get_amount()->format_i18n(); } $subscription_cancel_url = $subscription->get_cancel_url(); $subscription_renew_url = $subscription->get_renewal_url(); } $payment_id = gform_get_meta( rgar( $entry, 'id' ), 'pronamic_payment_id' ); $subscription_payment_id = gform_get_meta( rgar( $entry, 'id' ), 'pronamic_subscription_payment_id' ); /** * Bank transfer recipient details. */ // Use bank transfer details from last subscription payment if available. $payment = \get_pronamic_payment( $subscription_payment_id ); if ( null === $payment ) { $payment = \get_pronamic_payment( $payment_id ); } $bank_transfer_recipient_reference = ''; $bank_transfer_recipient_bank_name = ''; $bank_transfer_recipient_name = ''; $bank_transfer_recipient_iban = ''; $bank_transfer_recipient_bic = ''; $bank_transfer_recipient_city = ''; $bank_transfer_recipient_country = ''; $bank_transfer_recipient_account_number = ''; if ( null !== $payment ) { $bank_transfer_recipient = $payment->get_bank_transfer_recipient_details(); if ( null !== $bank_transfer_recipient ) { // Bank transfer reference. $bank_transfer_recipient_reference = \strval( $bank_transfer_recipient->get_reference() ); // Bank account. $bank_account = $bank_transfer_recipient->get_bank_account(); if ( null !== $bank_account ) { $bank_transfer_recipient_bank_name = \strval( $bank_account->get_bank_name() ); $bank_transfer_recipient_name = \strval( $bank_account->get_name() ); $bank_transfer_recipient_iban = \strval( $bank_account->get_iban() ); $bank_transfer_recipient_bic = \strval( $bank_account->get_bic() ); $bank_transfer_recipient_city = \strval( $bank_account->get_city() ); $bank_transfer_recipient_country = \strval( $bank_account->get_country() ); $bank_transfer_recipient_account_number = \strval( $bank_account->get_account_number() ); } } } // Pay again URL. $pay_again_url = \rgar( $entry, 'source_url' ); if ( null !== $payment ) { $pay_again_url = \add_query_arg( array( 'pay_again' => $payment->get_id(), 'key' => $payment->key, ), rgar( $entry, 'source_url' ) ); } // Replacements. $replacements = array( '{payment_status}' => rgar( $entry, 'payment_status' ), '{payment_date}' => rgar( $entry, 'payment_date' ), '{transaction_id}' => rgar( $entry, 'transaction_id' ), '{payment_amount}' => GFCommon::to_money( rgar( $entry, 'payment_amount' ), rgar( $entry, 'currency' ) ), '{pronamic_payment_id}' => $payment_id, '{pronamic_pay_again_url}' => $pay_again_url, '{pronamic_payment_bank_transfer_recipient_reference}' => $bank_transfer_recipient_reference, '{pronamic_payment_bank_transfer_recipient_bank_name}' => $bank_transfer_recipient_bank_name, '{pronamic_payment_bank_transfer_recipient_name}' => $bank_transfer_recipient_name, '{pronamic_payment_bank_transfer_recipient_iban}' => $bank_transfer_recipient_iban, '{pronamic_payment_bank_transfer_recipient_bic}' => $bank_transfer_recipient_bic, '{pronamic_payment_bank_transfer_recipient_city}' => $bank_transfer_recipient_city, '{pronamic_payment_bank_transfer_recipient_country}' => $bank_transfer_recipient_country, '{pronamic_payment_bank_transfer_recipient_account_number}' => $bank_transfer_recipient_account_number, '{pronamic_subscription_payment_id}' => $subscription_payment_id, '{pronamic_subscription_amount}' => $subscription_amount, '{pronamic_subscription_cancel_url}' => $subscription_cancel_url, '{pronamic_subscription_renew_url}' => $subscription_renew_url, '{pronamic_subscription_renewal_date}' => $subscription_renewal_date, ); if ( $url_encode ) { foreach ( $replacements as &$value ) { $value = rawurlencode( $value ); } } $text = strtr( $text, $replacements ); return $text; } /** * Filter currencies. * * @param array $currencies Available currencies. * * @return mixed */ public static function currencies( $currencies ) { if ( PaymentMethods::is_active( PaymentMethods::GULDEN ) ) { $currencies['NLG'] = array( 'name' => PaymentMethods::get_name( PaymentMethods::GULDEN ), 'symbol_left' => 'G', 'symbol_right' => '', 'symbol_padding' => ' ', 'thousand_separator' => '', 'decimal_separator' => '.', 'decimals' => 4, ); } return $currencies; } /** * Get delay actions based on active addons and built-in delay support. * * @return array */ public static function get_delay_actions() { $actions = array( 'gravityformsactivecampaign' => array( 'active' => false, 'meta_key_suffix' => 'activecampaign_subscription', 'delayed_payment_integration' => true, 'label' => __( 'Subscribing the user to ActiveCampaign', 'pronamic_ideal' ), ), 'gravityformsaweber' => array( 'active' => false, 'meta_key_suffix' => 'aweber_subscription', 'delayed_payment_integration' => true, 'label' => __( 'Subscribing the user to AWeber', 'pronamic_ideal' ), 'delay_callback' => function() { // @link https://github.com/wp-premium/gravityformsaweber/blob/1.4.2/aweber.php#L124-L125 \remove_action( 'gform_post_submission', array( 'GFAWeber', 'export' ), 10 ); }, 'process_callback' => function( $entry, $form ) { if ( Core_Util::class_method_exists( 'GFAWeber', 'export' ) ) { call_user_func( array( 'GFAWeber', 'export' ), $entry, $form, false ); } }, ), 'gravityformscampaignmonitor' => array( 'active' => false, 'meta_key_suffix' => 'campaignmonitor_subscription', 'delayed_payment_integration' => true, 'label' => __( 'Subscribing the user to Campaign Monitor', 'pronamic_ideal' ), 'delay_callback' => function() { // @link https://github.com/wp-premium/gravityformscampaignmonitor/blob/2.5.1/campaignmonitor.php#L124-L125 \remove_action( 'gform_after_submission', array( 'GFCampaignMonitor', 'export' ), 10 ); }, 'process_callback' => function( $entry, $form ) { // @link https://github.com/wp-premium/gravityformscampaignmonitor/blob/2.5.1/campaignmonitor.php#L1184 if ( Core_Util::class_method_exists( 'GFCampaignMonitor', 'export' ) ) { call_user_func( array( 'GFCampaignMonitor', 'export' ), $entry, $form, false ); } }, ), 'gravityformsmailchimp' => array( 'active' => false, 'meta_key_suffix' => 'mailchimp_subscription', 'delayed_payment_integration' => true, 'label' => __( 'Subscribing the user to MailChimp', 'pronamic_ideal' ), 'delay_callback' => function() { // @link https://github.com/wp-premium/gravityformsmailchimp/blob/2.4.1/mailchimp.php#L120-L121 \remove_action( 'gform_after_submission', array( 'GFMailChimp', 'export' ), 10 ); }, 'process_callback' => function( $entry, $form ) { // @link https://github.com/wp-premium/gravityformsmailchimp/blob/2.4.5/mailchimp.php#L1512. if ( Core_Util::class_method_exists( 'GFMailChimp', 'export' ) ) { call_user_func( array( 'GFMailChimp', 'export' ), $entry, $form, false ); } }, ), 'slicedinvoices' => array( 'active' => false, 'meta_key_suffix' => 'sliced_invoices', 'delayed_payment_integration' => false, 'label' => __( 'Creating quotes and invoices with Sliced Invoices', 'pronamic_ideal' ), ), 'gravityforms-moneybird' => array( 'active' => false, 'meta_key_suffix' => 'moneybird', 'delayed_payment_integration' => false, 'label' => __( 'Sending estimates and invoices with Moneybird', 'pronamic_ideal' ), ), 'gravityformstwilio' => array( 'active' => false, 'meta_key_suffix' => 'twilio', 'delayed_payment_integration' => true, 'label' => __( 'Sending data to Twilio', 'pronamic_ideal' ), ), 'gravityformswebhooks' => array( 'active' => false, 'meta_key_suffix' => 'webhooks', 'delayed_payment_integration' => false, 'label' => __( 'Sending a trigger to Webhooks', 'pronamic_ideal' ), ), 'gravityformsdropbox' => array( 'active' => false, 'meta_key_suffix' => 'dropbox', 'delayed_payment_integration' => false, 'label' => __( 'Uploading files to Dropbox', 'pronamic_ideal' ), ), 'gravityformszapier' => array( 'active' => class_exists( 'GFZapier' ), 'meta_key_suffix' => 'zapier', 'delayed_payment_integration' => false, 'label' => __( 'Sending data to Zapier', 'pronamic_ideal' ), 'delay_callback' => function() { // @link https://github.com/wp-premium/gravityformszapier/blob/1.4.2/zapier.php#L106 remove_action( 'gform_after_submission', array( 'GFZapier', 'send_form_data_to_zapier' ), 10 ); }, 'process_callback' => function( $entry, $form ) { // @link https://github.com/wp-premium/gravityformszapier/blob/1.4.2/zapier.php#L469-L533. if ( Core_Util::class_method_exists( 'GFZapier', 'send_form_data_to_zapier' ) ) { call_user_func( array( 'GFZapier', 'send_form_data_to_zapier' ), $entry, $form ); } }, ), 'gravityformsuserregistration' => array( 'active' => false, 'meta_key_suffix' => 'user_registration', 'delayed_payment_integration' => true, 'label' => __( 'Registering the user', 'pronamic_ideal' ), ), 'gravityflow' => array( 'active' => false, 'meta_key_suffix' => 'gravityflow', 'delayed_payment_integration' => true, 'label' => __( 'Start the Workflow once payment has been received.', 'pronamic_ideal' ), 'delay_callback' => function() { // @link https://github.com/gravityflow/gravityflow/blob/master/class-gravity-flow.php#L4711-L4720 }, 'process_callback' => function( $entry, $form ) { // @link https://github.com/gravityflow/gravityflow/blob/master/class-gravity-flow.php#L4730-L4746 if ( Core_Util::class_method_exists( 'Gravity_Flow', 'get_instance' ) ) { $gravityflow = \Gravity_Flow::get_instance(); $gravityflow->process_workflow( $form, $entry['id'] ); } }, ), ); $addons = GFAddOn::get_registered_addons(); foreach ( $addons as $class ) { $addon = call_user_func( array( $class, 'get_instance' ) ); $slug = $addon->get_slug(); if ( isset( $addon->delayed_payment_integration ) ) { if ( ! isset( $actions[ $slug ] ) ) { $actions[ $slug ] = array(); } $actions[ $slug ]['meta_key_suffix'] = $slug; $actions[ $slug ]['delayed_payment_integration'] = true; if ( isset( $addon->delayed_payment_integration['option_label'] ) ) { $actions[ $slug ]['label'] = $addon->delayed_payment_integration['option_label']; } } if ( isset( $actions[ $slug ] ) ) { $actions[ $slug ]['addon'] = $addon; $actions[ $slug ]['active'] = true; } } foreach ( $actions as $slug => $data ) { $actions[ $slug ]['meta_key'] = '_pronamic_pay_gf_delay_' . $data['meta_key_suffix']; } /** * Filters the delay actions to display on the payment feed settings page and to process. * * @since 2.4.0 * * @link https://github.com/wp-premium/gravityforms/blob/2.4.17/print-entry.php#L148-L163 * @link https://github.com/phpDocumentor/phpDocumentor/issues/1712 * * @param array $actions { * * Delay action. * * @var null|\GFAddon $addon Optional reference to a Gravity Forms add-on object. * @var bool $active Boolean flag to indicate the delay action can be enabled (add-on active). * @var string $meta_key Post meta key used to store meta value if the delay action is enabled. * @var bool $delayed_payment_integration Boolean flag to indicate the delay action is defined by a delayed payment integration. * @var string $label The label to show on the payment feed settings page. * @var callable $delay_callback Callback function which can be used to remove actions/filters to delay actions. * @var callable $process_callback Callback function to process the delay action. * * } */ $actions = \apply_filters( 'pronamic_pay_gravityforms_delay_actions', $actions ); return $actions; } /** * Maybe pre-populate form. * * @param array $args Form arguments. * @return array */ public function maybe_prepopulate_form( $args ) { // Check empty field values. if ( isset( $args['field_values'] ) && ! empty( $args['field_values'] ) ) { return $args; } // Get payment retry entry. $entry = $this->get_payment_retry_entry(); if ( null === $entry ) { return $args; } // Set field values. $field_values = array(); foreach ( $entry as $key => $value ) { $is_numeric = \is_numeric( $key ); $contains_dot = ( false !== \strpos( $key, '.' ) ); if ( ! $is_numeric && ! $contains_dot ) { continue; } $input_id = sprintf( 'input_%s', $key ); $input_id = \str_replace( '.', '_', $input_id ); $field_values[ $input_id ] = $value; } $args['field_values'] = $field_values; return $args; } /** * Allow field pre-population. * * @param array $form Form. * @return array */ public function allow_field_prepopulation( $form ) { // Get payment retry entry. $entry = $this->get_payment_retry_entry(); if ( null === $entry ) { return $form; } // Allow field pre-population. foreach ( $form['fields'] as &$field ) { $input_name = sprintf( 'input_%s', $field->id ); $input_name = \str_replace( '.', '_', $input_name ); $field->allowsPrepopulate = true; $field->inputName = $input_name; // Field inputs. if ( \is_array( $field['inputs'] ) ) { $new_inputs = $field['inputs']; foreach ( $new_inputs as &$input ) { $input_name = sprintf( 'input_%s', $input['id'] ); $input_name = \str_replace( '.', '_', $input_name ); $input['name'] = $input_name; } $field['inputs'] = $new_inputs; } } return $form; } /** * Get payment retry entry. * * @return null|array */ public function get_payment_retry_entry() { if ( ! \filter_has_var( \INPUT_GET, 'pay_again' ) ) { return null; } if ( ! \filter_has_var( \INPUT_GET, 'key' ) ) { return null; } // Check payment. $payment_id = \filter_input( \INPUT_GET, 'pay_again', \FILTER_SANITIZE_NUMBER_INT ); $payment = \get_pronamic_payment( $payment_id ); if ( null === $payment ) { return null; } // Check Gravity Forms source. if ( self::SLUG !== $payment->get_source() ) { return null; } // Check if payment key is valid. $key = filter_input( INPUT_GET, 'key', FILTER_SANITIZE_STRING ); if ( empty( $payment->key ) ) { return null; } if ( $key !== $payment->key ) { return null; } // Get entry. $entry_id = $payment->get_source_id(); $entry = RGFormsModel::get_lead( $entry_id ); if ( false === $entry ) { return null; } return $entry; } }