Advertisement
Guest User

Untitled

a guest
Aug 31st, 2016
459
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 49.71 KB | None | 0 0
  1.     <?php
  2.  
  3. GFForms::include_payment_addon_framework();
  4.  
  5. class GFPayPalPaymentsPro extends GFPaymentAddOn {
  6.     protected $_version = GF_PAYPALPAYMENTSPRO_VERSION;
  7.     protected $_min_gravityforms_version = '1.9.16';
  8.     protected $_slug = 'gravityformspaypalpaymentspro';
  9.     protected $_path = 'gravityformspaypalpaymentspro/paypalpaymentspro.php';
  10.     protected $_full_path = __FILE__;
  11.     protected $_url = 'http://www.gravityforms.com';
  12.     protected $_title = 'Gravity Forms PayPal Payments Pro Add-On';
  13.     protected $_short_title = 'PayPal Payments Pro';
  14.     protected $_supports_callbacks = true;
  15.     protected $_requires_credit_card = true;
  16.     protected $_enable_rg_autoupgrade = true;
  17.  
  18.     /**
  19.      * Members plugin integration
  20.      */
  21.     protected $_capabilities = array(
  22.             'gravityforms_paypalpaymentspro',
  23.             'gravityforms_paypalpaymentspro_uninstall',
  24.             'gravityforms_paypalpaymentspro_plugin_page'
  25.     );
  26.  
  27.     /**
  28.      * Permissions
  29.      */
  30.     protected $_capabilities_settings_page = 'gravityforms_paypalpaymentspro';
  31.     protected $_capabilities_form_settings = 'gravityforms_paypalpaymentspro';
  32.     protected $_capabilities_uninstall = 'gravityforms_paypalpaymentspro_uninstall';
  33.     protected $_capabilities_plugin_page = 'gravityforms_paypalpaymentspro_plugin_page';
  34.    
  35.     private static $_instance = null;
  36.  
  37.     /**
  38.      * Get an instance of this class.
  39.      *
  40.      * @return GFPayPalPaymentsPro
  41.      */
  42.     public static function get_instance() {
  43.         if ( self::$_instance == null ) {
  44.             self::$_instance = new GFPayPalPaymentsPro();
  45.         }
  46.  
  47.         return self::$_instance;
  48.     }
  49.  
  50.     // # ADMIN FUNCTIONS -----------------------------------------------------------------------------------------------
  51.  
  52.     // ------- Plugin settings -------
  53.  
  54.     /**
  55.      * Configures the settings which should be rendered on the add-on settings tab.
  56.      *
  57.      * @return array
  58.      */
  59.     public function plugin_settings_fields() {
  60.         $description = '<p style="text-align: left;">' . sprintf( esc_html__( 'PayPal Payments Pro is a merchant account and gateway in one. Use Gravity Forms to collect payment information and automatically integrate to your PayPal Payments Pro account. If you don\'t have a PayPal Payments Pro account, you can %ssign up for one here%s', 'gravityformspaypalpaymentspro' ), '<a href="https://registration.paypal.com/welcomePage.do?bundleCode=C3&country=US&partner=PayPal" target="_blank">', '</a>' ) . '</p>';
  61.         return array(
  62.             array(
  63.                 'description' => $description,
  64.                 'fields'      => array(
  65.                     array(
  66.                         'name'          => 'mode',
  67.                         'label'         => esc_html__( 'API', 'gravityformspaypalpaymentspro' ),
  68.                         'type'          => 'radio',
  69.                         'default_value' => 'production',
  70.                         'choices'       => array(
  71.                             array(
  72.                                 'label'     => esc_html__( 'Live', 'gravityformspaypalpaymentspro' ),
  73.                                 'value'     => 'production',
  74.                             ),
  75.                             array(
  76.                                 'label'     => esc_html__( 'Sandbox', 'gravityformspaypalpaymentspro' ),
  77.                                 'value'     => 'test',
  78.                             ),
  79.                         ),
  80.                         'horizontal'    => true,
  81.                     ),
  82.                     array(
  83.                         'name'              => 'username',
  84.                         'label'             => esc_html__( 'Username', 'gravityformspaypalpaymentspro' ),
  85.                         'type'              => 'text',
  86.                         'class'             => 'medium',
  87.                         'feedback_callback' => array( $this, 'is_valid_api_credentials' ),
  88.                     ),
  89.                     array(
  90.                         'name'     => 'password',
  91.                         'label'    => esc_html__( 'Password', 'gravityformspaypalpaymentspro' ),
  92.                         'type'     => 'password',
  93.                         'class'    => 'medium',
  94.                         'feedback_callback' => array( $this, 'check_valid_api_credential_setting' ),
  95.                     ),
  96.                     array(
  97.                         'name'     => 'vendor',
  98.                         'label'    => esc_html__( 'Vendor (optional)', 'gravityformspaypalpaymentspro' ),
  99.                         'type'     => 'vendor',
  100.                         'class'    => 'medium',
  101.                         'feedback_callback' => array( $this, 'check_valid_api_credential_setting' ),
  102.                     ),
  103.                     array(
  104.                         'name'          => 'partner',
  105.                         'label'         => esc_html__( 'Partner', 'gravityformspaypalpaymentspro' ),
  106.                         'type'          => 'partner',
  107.                         'class'         => 'medium',
  108.                         'default_value' => 'PayPal',
  109.                         'feedback_callback' => array( $this, 'check_valid_api_credential_setting' ),
  110.                     ),
  111.                 ),
  112.             ),
  113.         );
  114.     }
  115.  
  116.     /**
  117.      * Define the markup for the password type field.
  118.      *
  119.      * @param array $field The field properties.
  120.      * @param bool|true $echo Should the setting markup be echoed.
  121.      *
  122.      * @return string|void
  123.      */
  124.     public function settings_password( $field, $echo = true ) {
  125.  
  126.         $field['type'] = 'text';
  127.  
  128.         $password_field = $this->settings_text( $field, false );
  129.  
  130.         //switch type="text" to type="password" so the password is not visible
  131.         $password_field = str_replace( 'type="text"','type="password"', $password_field );
  132.  
  133.         if ( $echo ) {
  134.             echo $password_field;
  135.         }
  136.  
  137.         return $password_field;
  138.  
  139.     }
  140.  
  141.     /**
  142.      * Define the markup for the vendor type field.
  143.      *
  144.      * @param array $field The field properties.
  145.      * @param bool|true $echo Should the setting markup be echoed.
  146.      *
  147.      * @return string|void
  148.      */
  149.     public function settings_vendor( $field, $echo = true ) {
  150.  
  151.         $field['type'] = 'text';
  152.  
  153.         $vendor_field = $this->settings_text( $field, false );
  154.  
  155.         $caption = '<small>' . sprintf( esc_html__( 'Your merchant login ID if different from Username above.', 'gravityformspaypalpaymentspro' ) ) . '</small>';
  156.  
  157.         if ( $echo ) {
  158.             echo $vendor_field . '</br>' . $caption;
  159.         }
  160.  
  161.         return $vendor_field . '</br>' . $caption;
  162.  
  163.     }
  164.  
  165.     /**
  166.      * Define the markup for the partner type field.
  167.      *
  168.      * @param array $field The field properties.
  169.      * @param bool|true $echo Should the setting markup be echoed.
  170.      *
  171.      * @return string|void
  172.      */
  173.     public function settings_partner( $field, $echo = true ) {
  174.  
  175.         $field['type'] = 'text';
  176.  
  177.         $partner_field = $this->settings_text( $field, false );
  178.  
  179.         $caption = '<small>' . sprintf( esc_html__( 'If you have registered with a PayPal Reseller, enter their ID above.', 'gravityformspaypalpaymentspro' ) ) . '</small>';
  180.  
  181.         if ( $echo ) {
  182.             echo $partner_field . '</br>' . $caption;
  183.         }
  184.  
  185.         return $partner_field . '</br>' . $caption;
  186.  
  187.     }
  188.  
  189.     //-------- Form Settings ---------
  190.  
  191.     /**
  192.      * Prevent feeds being listed or created if the api keys aren't valid.
  193.      *
  194.      * @return bool
  195.      */
  196.     public function can_create_feed() {
  197.         return $this->is_valid_api_credentials();
  198.     }
  199.  
  200.     /**
  201.      * Configures the settings which should be rendered on the feed edit page.
  202.      *
  203.      * @return array The feed settings.
  204.      */
  205.     public function feed_settings_fields() {
  206.         $default_settings = parent::feed_settings_fields();
  207.  
  208.         //remove default options before adding custom
  209.         $default_settings = parent::remove_field( 'options', $default_settings );
  210.         $default_settings = parent::remove_field( 'billingCycle', $default_settings );
  211.         $default_settings = parent::remove_field( 'trial', $default_settings );
  212.  
  213.         //add pay period if subscription
  214.         if ( $this->get_setting( 'transactionType' ) == 'subscription' ) {
  215.             $pay_period_field = array(
  216.                 'name'     => 'payPeriod',
  217.                 'label'    => esc_html__( 'Pay Period', 'gravityformspaypalpaymentspro' ),
  218.                 'type'     => 'select',
  219.                 'choices' => array(
  220.                                 array( 'label' => esc_html__( 'Weekly', 'gravityformspaypalpaymentspro' ), 'value' => 'WEEK' ),
  221.                                 array( 'label' => esc_html__( 'Every Two Weeks', 'gravityformspaypalpaymentspro' ), 'value' => 'BIWK' ),
  222.                                 array( 'label' => esc_html__( 'Twice Every Month', 'gravityformspaypalpaymentspro' ), 'value' => 'SMMO' ),
  223.                                 array( 'label' => esc_html__( 'Every Four Weeks', 'gravityformspaypalpaymentspro' ), 'value' => 'FRWK' ),
  224.                                 array( 'label' => esc_html__( 'Monthly', 'gravityformspaypalpaymentspro' ), 'value' => 'MONT' ),
  225.                                 array( 'label' => esc_html__( 'Quarterly', 'gravityformspaypalpaymentspro' ), 'value' => 'QTER' ),
  226.                                 array( 'label' => esc_html__( 'Twice Every Year', 'gravityformspaypalpaymentspro' ), 'value' => 'SMYR' ),
  227.                                 array( 'label' => esc_html__( 'Yearly', 'gravityformspaypalpaymentspro' ), 'value' => 'YEAR' ),
  228.                             ),
  229.                 'tooltip'  => '<h6>' . esc_html__( 'Pay Period', 'gravityformspaypalpaymentspro' ) . '</h6>' . esc_html__( 'Select pay period.  This determines how often the recurring payment should occur.', 'gravityformspaypalpaymentspro' ),
  230.             );
  231.             $default_settings = $this->add_field_after( 'recurringAmount', $pay_period_field, $default_settings );
  232.  
  233.             //Add post fields if form has a post
  234.             $form = $this->get_current_form();
  235.  
  236.             if ( GFCommon::has_post_field( $form['fields'] ) ) {
  237.                 $post_settings = array(
  238.                         'name'    => 'post_checkboxes',
  239.                         'label'   => esc_html__( 'Posts', 'gravityformspaypalpaymentspro' ),
  240.                         'type'    => 'checkbox',
  241.                         'tooltip' => '<h6>' . esc_html__( 'Posts', 'gravityformspaypalpaymentspro' ) . '</h6>' . esc_html__( 'Enable this option if you would like to change the post status when a subscription is cancelled.', 'gravityformspaypalpaymentspro' ),
  242.                         'choices' => array(
  243.                                 array(
  244.                                         'label'    => esc_html__( 'Update Post when subscription is cancelled.', 'gravityformspaypalpaymentspro' ),
  245.                                         'name'     => 'change_post_status',
  246.                                         'onChange' => 'var action = this.checked ? "draft" : ""; jQuery("#update_post_action").val(action);',
  247.                                 ),
  248.                         ),
  249.                 );
  250.  
  251.                 $default_settings = $this->add_field_after( 'billingInformation', $post_settings, $default_settings );
  252.             }
  253.         }
  254.  
  255.         $fields = array(
  256.             array(
  257.                 'name'      => 'apiSettingsEnabled',
  258.                 'label'     => esc_html__( 'API Settings', 'gravityformspaypalpaymentspro' ),
  259.                 'type'      => 'checkbox',
  260.                 'tooltip'   => '<h6>' . esc_html__( 'API Settings', 'gravityformspaypalpaymentspro' ) . '</h6>' . esc_html__( 'Override the settings provided on the PayPal Payments Pro Settings page and use these instead for this feed.', 'gravityformspaypalpaymentspro' ),
  261.                 'onchange' => "if(jQuery(this).prop('checked')){
  262.                                         jQuery('#gaddon-setting-row-overrideMode').show();
  263.                                         jQuery('#gaddon-setting-row-overrideUsername').show();
  264.                                         jQuery('#gaddon-setting-row-overridePassword').show();
  265.                                         jQuery('#gaddon-setting-row-overrideVendor').show();
  266.                                         jQuery('#gaddon-setting-row-overridePartner').show();
  267.                                     } else {
  268.                                         jQuery('#gaddon-setting-row-overrideMode').hide();
  269.                                         jQuery('#gaddon-setting-row-overrideUsername').hide();
  270.                                         jQuery('#gaddon-setting-row-overridePassword').hide();
  271.                                         jQuery('#gaddon-setting-row-overrideVendor').hide();
  272.                                         jQuery('#gaddon-setting-row-overridePartner').hide();
  273.                                         jQuery('#overrideUsername').val('');
  274.                                         jQuery('#overridePassword').val('');
  275.                                         jQuery('#overrideVendor').val('');
  276.                                         //jQuery('#overridePartner').val('');
  277.                                         jQuery('i').removeClass('icon-check fa-check gf_valid');
  278.                                     }",
  279.                 'choices'   => array(
  280.                     array(
  281.                         'label' => 'Override Default Settings',
  282.                         'name'  => 'apiSettingsEnabled',
  283.                     ),
  284.                 )
  285.             ),
  286.             array(
  287.                 'name'          => 'overrideMode',
  288.                 'label'         => esc_html__( 'API', 'gravityformspaypalpaymentspro' ),
  289.                 'type'          => 'radio',
  290.                 'hidden'        => ! $this->get_setting( 'apiSettingsEnabled' ),
  291.                 'tooltip'       => '<h6>' . esc_html__( 'API', 'gravityformspaypalpaymentspro' ) . '</h6>' . esc_html__( 'Select either Production or Sandbox API to override the chosen mode on the PayPal Payments Pro Settings page.', 'gravityformspaypalpaymentspro' ),
  292.                 'choices'       => array(
  293.                     array(
  294.                         'label'     => esc_html__( 'Production', 'gravityformspaypalpaymentspro' ),
  295.                         'value'     => 'production',
  296.                     ),
  297.                     array(
  298.                         'label'     => esc_html__( 'Sandbox', 'gravityformspaypalpaymentspro' ),
  299.                         'value'     => 'test',
  300.                     ),
  301.                 ),
  302.                 'horizontal'    => true,
  303.             ),
  304.             array(
  305.                 'name'     => 'overrideUsername',
  306.                 'label'    => esc_html__( 'Username', 'gravityformspaypalpaymentspro' ),
  307.                 'type'     => 'text',
  308.                 'class'    => 'medium',
  309.                 'hidden'        => ! $this->get_setting( 'apiSettingsEnabled' ),
  310.                 'tooltip'       => '<h6>' . esc_html__( 'Username', 'gravityformspaypalpaymentspro' ) . '</h6>' . esc_html__( 'Enter a new value to override the Username on the PayPal Payments Pro Settings page.', 'gravityformspaypalpaymentspro' ),
  311.                 'feedback_callback' => array( $this, 'is_valid_override_credentials' ),
  312.             ),
  313.             array(
  314.                 'name'     => 'overridePassword',
  315.                 'label'    => esc_html__( 'Password', 'gravityformspaypalpaymentspro' ),
  316.                 'type'     => 'password',
  317.                 'class'    => 'medium',
  318.                 'hidden'        => ! $this->get_setting( 'apiSettingsEnabled' ),
  319.                 'tooltip'       => '<h6>' . esc_html__( 'Password', 'gravityformspaypalpaymentspro' ) . '</h6>' . esc_html__( 'Enter a new value to override the Password on the PayPal Payments Pro Settings page.', 'gravityformspaypalpaymentspro' ),
  320.                 'feedback_callback' => array( $this, 'check_valid_override_credential_setting' ),
  321.             ),
  322.             array(
  323.                 'name'     => 'overrideVendor',
  324.                 'label'    => esc_html__( 'Vendor (optional)', 'gravityformspaypalpaymentspro' ),
  325.                 'type'     => 'vendor',
  326.                 'class'    => 'medium',
  327.                 'hidden'        => ! $this->get_setting( 'apiSettingsEnabled' ),
  328.                 'tooltip'       => '<h6>' . esc_html__( 'Vendor', 'gravityformspaypalpaymentspro' ) . '</h6>' . esc_html__( 'Enter a new value to override the Vendor on the PayPal Payments Pro Settings page.', 'gravityformspaypalpaymentspro' ),
  329.                 'feedback_callback' => array( $this, 'check_valid_override_credential_setting' ),
  330.             ),
  331.             array(
  332.                 'name'          => 'overridePartner',
  333.                 'label'         => esc_html__( 'Partner', 'gravityformspaypalpaymentspro' ),
  334.                 'type'          => 'partner',
  335.                 'class'         => 'medium',
  336.                 'hidden'        => ! $this->get_setting( 'apiSettingsEnabled' ),
  337.                 'tooltip'       => '<h6>' . esc_html__( 'Partner', 'gravityformspaypalpaymentspro' ) . '</h6>' . esc_html__( 'Enter a new value to override the Partner on the PayPal Payments Pro Settings page.', 'gravityformspaypalpaymentspro' ),
  338.                 'default_value' => 'PayPal',
  339.                 'feedback_callback' => array( $this, 'check_valid_override_credential_setting' ),
  340.             ),
  341.         );
  342.  
  343.         $default_settings = $this->add_field_after( 'conditionalLogic', $fields, $default_settings );
  344.  
  345.         return $default_settings;
  346.     }
  347.  
  348.     /**
  349.      * Returns the markup for the change post status checkbox item.
  350.      *
  351.      * @param array $choice The choice properties.
  352.      * @param string $attributes The attributes for the input tag.
  353.      * @param string $value Currently selection (1 if field has been checked. 0 or null otherwise).
  354.      * @param string $tooltip The tooltip for this checkbox item.
  355.      *
  356.      * @return string
  357.      */
  358.     public function checkbox_input_change_post_status( $choice, $attributes, $value, $tooltip ) {
  359.         $markup = $this->checkbox_input( $choice, $attributes, $value, $tooltip );
  360.  
  361.         $dropdown_field = array(
  362.             'name'     => 'update_post_action',
  363.             'choices'  => array(
  364.                 array( 'label' => '' ),
  365.                 array( 'label' => esc_html__( 'Mark Post as Draft', 'gravityformspaypalpaymentspro' ), 'value' => 'draft' ),
  366.                 array( 'label' => esc_html__( 'Delete Post', 'gravityformspaypalpaymentspro' ), 'value' => 'delete' ),
  367.  
  368.             ),
  369.             'onChange' => "var checked = jQuery(this).val() ? 'checked' : false; jQuery('#change_post_status').attr('checked', checked);",
  370.         );
  371.         $markup .= '&nbsp;&nbsp;' . $this->settings_select( $dropdown_field, false );
  372.  
  373.         return $markup;
  374.     }
  375.  
  376.     /**
  377.      * Prepend the name fields to the default billing_info_fields added by the framework.
  378.      *
  379.      * @return array
  380.      */
  381.     public function billing_info_fields() {
  382.         $fields = array(
  383.                 array(
  384.                         'name'     => 'lastName',
  385.                         'label'    => esc_html__( 'Last Name', 'gravityformspaypalpaymentspro' ),
  386.                         'required' => false
  387.                 ),
  388.                 array(
  389.                         'name'     => 'firstName',
  390.                         'label'    => esc_html__( 'First Name', 'gravityformspaypalpaymentspro' ),
  391.                         'required' => false
  392.                 )
  393.         );
  394.  
  395.         return array_merge( $fields, parent::billing_info_fields() );
  396.     }
  397.  
  398.     /**
  399.      * Add supported notification events.
  400.      *
  401.      * @param array $form The form currently being processed.
  402.      *
  403.      * @return array
  404.      */
  405.     public function supported_notification_events( $form ) {
  406.         if ( ! $this->has_feed( $form['id'] ) ) {
  407.             return false;
  408.         }
  409.  
  410.         return array(
  411.                 'complete_payment'          => esc_html__( 'Payment Completed', 'gravityformspaypalpaymentspro' ),
  412.                 'create_subscription'       => esc_html__( 'Subscription Created', 'gravityformspaypalpaymentspro' ),
  413.                 'cancel_subscription'       => esc_html__( 'Subscription Canceled', 'gravityformspaypalpaymentspro' ),
  414.                 'expire_subscription'       => esc_html__( 'Subscription Expired', 'gravityformspaypalpaymentspro' ),
  415.                 'add_subscription_payment'  => esc_html__( 'Subscription Payment Added', 'gravityformspaypalpaymentspro' ),
  416.         );
  417.     }
  418.  
  419.     //-------- Entry Detail ---------
  420.  
  421.     /**
  422.      * Handle cancelling the subscription from the entry detail page.
  423.      *
  424.      * @param array $entry The entry object currently being processed.
  425.      * @param array $feed The feed object currently being processed.
  426.      *
  427.      * @return bool
  428.      */
  429.     public function cancel( $entry, $feed ) {
  430.  
  431.         $args = array( 'TRXTYPE'       => 'R',
  432.                        'TENDER'        => 'C',
  433.                        'ORIGPROFILEID' => $entry['transaction_id'],
  434.                        'ACTION'        => 'C'
  435.         );
  436.  
  437.         $settings = $this->get_plugin_settings();
  438.         $response = $this->post_to_payflow( $args, $settings, $entry['form_id'] );
  439.  
  440.         if ( ! empty( $response ) && $response['RESULT'] == '0' ) {
  441.             return true;
  442.         }
  443.  
  444.         return false;
  445.     }
  446.  
  447.     /**
  448.      * Check if the current entry was processed by this add-on.
  449.      *
  450.      * @param int $entry_id The ID of the current Entry.
  451.      *
  452.      * @return bool
  453.      */
  454.     public function is_payment_gateway( $entry_id ) {
  455.  
  456.         if ( $this->is_payment_gateway ) {
  457.             return true;
  458.         }
  459.  
  460.         $gateway = gform_get_meta( $entry_id, 'payment_gateway' );
  461.  
  462.         return in_array( $gateway, array( 'paypalpaymentspro', $this->_slug ) );
  463.     }
  464.  
  465.  
  466.     // # SUBMISSION ----------------------------------------------------------------------------------------------------
  467.  
  468.     /**
  469.      * Authorize and capture the transaction for the product & services type feed.
  470.      *
  471.      * @param array $feed The feed object currently being processed.
  472.      * @param array $submission_data The customer and transaction data.
  473.      * @param array $form The form object currently being processed.
  474.      * @param array $entry The entry object currently being processed.
  475.      *
  476.      * @return array
  477.      */
  478.     public function authorize( $feed, $submission_data, $form, $entry ) {
  479.  
  480.         // Credit Card Information
  481.         $args = $this->prepare_credit_card_transaction( $feed, $submission_data, $form, $entry );
  482.  
  483.         // setting up sale transaction parameters
  484.         $args['TRXTYPE'] = 'S';
  485.  
  486.         /**
  487.          * Filter the transaction properties for the product and service feed.
  488.          *
  489.          * @since 1.0.0
  490.          * @since 2.0.0 Added the $submission_data, $feed, and $entry parameters.
  491.          *
  492.          * @param array $args The transaction properties.
  493.          * @param int $form_id The ID of the form currently being processed.
  494.          * @param array $submission_data The customer and transaction data.
  495.          * @param array $feed The feed object currently being processed.
  496.          * @param array $entry The entry object currently being processed.
  497.          */
  498.         $args = apply_filters( 'gform_paypalpaymentspro_args_before_payment', $args, $form['id'], $submission_data, $feed, $entry );
  499.  
  500.         $settings = $this->get_plugin_settings();
  501.         $response = $this->post_to_payflow( $args, $settings, $form['id'] );
  502.  
  503.         if ( isset( $response['RESULT'] ) && $response['RESULT'] == 0 ) {
  504.             $this->log_debug( __METHOD__ . "(): Funds captured successfully. Amount: {$args['AMT']}. Transaction Id: {$response['PNREF']}." );
  505.             $captured_payment = array( 'is_success'     => true,
  506.                                        'error_message'  => '',
  507.                                        'transaction_id' => $response['PNREF'],
  508.                                        'amount'         => $args['AMT']
  509.             );
  510.             $auth             = array( 'is_authorized'    => true,
  511.                                        'transaction_id'   => $response['PNREF'],
  512.                                        'captured_payment' => $captured_payment
  513.             );
  514.  
  515.             $config = $this->get_config( $feed, $submission_data );
  516.  
  517.             // deprecated
  518.             do_action( 'gform_paypalpaymentspro_post_capture', $args['AMT'], $entry, $form, $config );
  519.  
  520.         } else {
  521.             $this->log_error( __METHOD__ . '(): Funds could not be captured.' );
  522.             $auth = array( 'is_success'     => false,
  523.                            'transaction_id' => $response['PNREF'],
  524.                            'error_message'  => $response['RESPMSG']
  525.             );
  526.         }
  527.  
  528.         return $auth;
  529.  
  530.     }
  531.  
  532.     /**
  533.      * Create a recurring profile for the user and return any errors which occur.
  534.      *
  535.      * @param array $feed The feed object currently being processed.
  536.      * @param array $submission_data The customer and transaction data.
  537.      * @param array $form The form object currently being processed.
  538.      * @param array $entry The entry object currently being processed.
  539.      *
  540.      * @return array
  541.      */
  542.     public function subscribe( $feed, $submission_data, $form, $entry ) {
  543.  
  544.         $subscription = $this->prepare_credit_card_transaction( $feed, $submission_data, $form, $entry );
  545.  
  546.         //setting up recurring transaction parameters
  547.         $subscription['TRXTYPE'] = 'R';
  548.         $subscription['ACTION']  = 'A';
  549.  
  550.         $subscription['START']             = date( 'mdY', mktime( 0, 0, 0, date( 'm' ), date( 'd' ) + 1, date( 'y' ) ) );
  551.         $subscription['PROFILENAME']       = $subscription['FIRSTNAME'] . " " . $subscription['LASTNAME'];
  552.         $subscription['MAXFAILEDPAYMENTS'] = '0';
  553.         $subscription['PAYPERIOD']         = $feed['meta']['payPeriod'];
  554.         $subscription['TERM']              = $feed['meta']['recurringTimes'];
  555.         $subscription['AMT']               = $submission_data['payment_amount'];
  556.  
  557.         if ( $feed['meta']['setupFee_enabled'] && ! empty( $submission_data['setup_fee'] ) && $submission_data['setup_fee'] > 0 ) {
  558.             $subscription['OPTIONALTRX']    = 'S';
  559.             $subscription['OPTIONALTRXAMT'] = $submission_data['setup_fee'];
  560.         } else {
  561.             $subscription['OPTIONALTRX'] = 'A';
  562.         }
  563.  
  564.         /**
  565.          * Filter the subscription transaction properties.
  566.          *
  567.          * @since 1.0.0
  568.          * @since 2.0.0 Added the $submission_data, $feed, and $entry parameters.
  569.          *
  570.          * @param array $subscription The subscription transaction properties.
  571.          * @param int $form_id The ID of the form currently being processed.
  572.          * @param array $submission_data The customer and transaction data.
  573.          * @param array $feed The feed object currently being processed.
  574.          * @param array $entry The entry object currently being processed.
  575.          */
  576.         $subscription = apply_filters( 'gform_paypalpaymentspro_args_before_subscription', $subscription, $form['id'], $submission_data, $feed, $entry );
  577.  
  578.         $this->log_debug( __METHOD__ . '(): Creating recurring profile.' );
  579.         $settings = $this->get_plugin_settings();
  580.         $response = $this->post_to_payflow( $subscription, $settings, $form['id'] );
  581.  
  582.         if ( $response['RESULT'] == 0 ) {
  583.  
  584.             $subscription_id = $response['PROFILEID'];
  585.             $this->log_debug( __METHOD__ . "(): Subscription created successfully. Subscription Id: {$subscription_id}" );
  586.  
  587.             if ( $feed['meta']['setupFee_enabled'] ) {
  588.                 $captured_payment    = array(
  589.                         'is_success'     => true,
  590.                         'transaction_id' => rgar( $response, 'RPREF' ),
  591.                         'amount'         => $submission_data['setup_fee']
  592.                 );
  593.                 $subscription_result = array(
  594.                         'is_success'       => true,
  595.                         'subscription_id'  => $subscription_id,
  596.                         'captured_payment' => $captured_payment,
  597.                         'amount'           => $subscription['AMT']
  598.                 );
  599.             } else {
  600.                 $subscription_result = array( 'is_success'      => true,
  601.                                               'subscription_id' => $subscription_id,
  602.                                               'amount'          => $subscription['AMT']
  603.                 );
  604.             }
  605.  
  606.         } else {
  607.             $this->log_error( __METHOD__ . '(): There was an error creating Subscription.' );
  608.             $error_message       = $this->get_error_message( $response );
  609.             $subscription_result = array( 'is_success' => false, 'error_message' => $error_message );
  610.         }
  611.  
  612.         return $subscription_result;
  613.     }
  614.  
  615.  
  616.     // # CRON JOB ------------------------------------------------------------------------------------------------------
  617.  
  618.     /**
  619.      * Check subscription status; Active subscriptions will be checked to see if their status needs to be updated.
  620.      */
  621.     public function check_status() {
  622.         // this is where we will check subscription status and update as needed
  623.         $this->log_debug( __METHOD__ . '(): Checking subscription status.' );
  624.  
  625.         // getting all PayPal Payments Pro subscription feeds
  626.         $recurring_feeds = $this->get_feeds_by_slug( $this->_slug );
  627.  
  628.         foreach ( $recurring_feeds as $feed ) {
  629.  
  630.             // process renewal's if authorize.net feed is subscription feed
  631.             if ( $feed['meta']['transactionType'] == 'subscription' ) {
  632.  
  633.                 $form_id   = $feed['form_id'];
  634.                 $querytime = strtotime( gmdate( 'Y-m-d' ) );
  635.                 $querydate = gmdate( 'mdY', $querytime );
  636.  
  637.                 // finding leads with a late payment date
  638.                 global $wpdb;
  639.  
  640.                 $results = $wpdb->get_results( "SELECT l.id, l.transaction_id, m.meta_value as payment_date
  641.                                                FROM {$wpdb->prefix}rg_lead l
  642.                                                INNER JOIN {$wpdb->prefix}rg_lead_meta m ON l.id = m.lead_id
  643.                                                WHERE l.form_id={$form_id}
  644.                                                AND payment_status = 'Active'
  645.                                                AND meta_key = 'subscription_payment_date'
  646.                                                AND meta_value < '{$querydate}'" );
  647.  
  648.                 $this->log_debug( __METHOD__ . '(): Leads with late payment.' );
  649.                 foreach ( $results as $result ) {
  650.  
  651.                     $this->log_debug( print_r( $result ) );
  652.  
  653.                     //Getting entry
  654.                     $entry_id = $result->id;
  655.                     $entry    = GFAPI::get_entry( $entry_id );
  656.  
  657.                     $subscription_id = $result->transaction_id;
  658.                     // Get the subscription profile status
  659.                     $profile_status_request                  = array();
  660.                     $profile_status_request['TRXTYPE']       = 'R';
  661.                     $profile_status_request['TENDER']        = 'C';
  662.                     $profile_status_request['ACTION']        = 'I';
  663.                     $profile_status_request['ORIGPROFILEID'] = $subscription_id;
  664.                     //$profile_status_request['PAYMENTHISTORY'] = 'Y';
  665.  
  666.                     $settings       = $this->get_plugin_settings();
  667.                     $profile_status = $this->post_to_payflow( $profile_status_request, $settings, $form_id );
  668.  
  669.                     $status          = $profile_status['STATUS'];
  670.                     $subscription_id = $profile_status['PROFILEID'];
  671.  
  672.                     switch ( strtolower( $status ) ) {
  673.                         case 'active' :
  674.  
  675.                             // getting new payment date and count
  676.                             $new_payment_date   = $profile_status['NEXTPAYMENT'];
  677.                             $new_payment_count  = $profile_status['NEXTPAYMENTNUM'] - 1;
  678.                             $new_payment_amount = $profile_status['AMT'];
  679.  
  680.                             if ( $new_payment_date > $querydate ) {
  681.  
  682.                                 // update subscription payment and lead information
  683.                                 gform_update_meta( $entry_id, 'subscription_payment_count', $new_payment_count );
  684.                                 gform_update_meta( $entry_id, 'subscription_payment_date', $new_payment_date );
  685.  
  686.                                 $action = array( 'amount'          => $new_payment_amount,
  687.                                                  'subscription_id' => $subscription_id,
  688.                                 );
  689.                                 $this->add_subscription_payment( $entry, $action );
  690.  
  691.                                 //deprecated
  692.                                 do_action( 'gform_paypalpaymentspro_after_subscription_payment', $entry, $subscription_id, $profile_status['AMT'] );
  693.                             }
  694.  
  695.                             break;
  696.  
  697.                         case 'expired' :
  698.  
  699.                             $action = array( 'subscription_id' => $subscription_id );
  700.                             $this->expire_subscription( $entry, $action );
  701.  
  702.                             //deprecated
  703.                             do_action( 'gform_paypalpaymentspro_subscription_expired', $entry, $subscription_id );
  704.  
  705.                             break;
  706.  
  707.                         case 'too many failures':
  708.                         case 'deactivated by merchant':
  709.                             $this->cancel_subscription( $entry, $feed );
  710.                             do_action( 'gform_paypalpaymentspro_subscription_canceled', $entry, $subscription_id );
  711.                             break;
  712.  
  713.                         default:
  714.                             $this->cancel_subscription( $entry, $feed );
  715.                             do_action( 'gform_paypalpaymentspro_subscription_canceled', $entry, $subscription_id );
  716.                             break;
  717.                     }
  718.  
  719.                 }
  720.  
  721.             }
  722.  
  723.         }
  724.     }
  725.  
  726.  
  727.     // # HELPERS -------------------------------------------------------------------------------------------------------
  728.  
  729.     /**
  730.      * Maybe validate the override credentials.
  731.      *
  732.      * @return bool
  733.      */
  734.     public function is_valid_override_credentials() {
  735.         //get override credentials
  736.         global $valid_override_username;
  737.         $valid_override_username = false;
  738.  
  739.         $apiSettingsEnabled = $this->get_setting( 'apiSettingsEnabled' );
  740.         if ( $apiSettingsEnabled ) {
  741.             $custom_settings['mode']     = $this->get_setting( 'overrideMode' );
  742.             $custom_settings['username'] = $this->get_setting( 'overrideUsername' );
  743.             $custom_settings['password'] = $this->get_setting( 'overridePassword' );
  744.             $custom_settings['vendor']   = $this->get_setting( 'overrideVendor' );
  745.             $custom_settings['partner']  = $this->get_setting( 'overridePartner' );
  746.  
  747.             $valid_override_username = $this->is_valid_credentials( $custom_settings );
  748.         }
  749.  
  750.         return $valid_override_username;
  751.     }
  752.  
  753.     /**
  754.      * Validate the API credentials.
  755.      *
  756.      * @return bool
  757.      */
  758.     public function is_valid_api_credentials() {
  759.         //get api credentials
  760.         $settings = $this->get_plugin_settings();
  761.         global $valid_username;
  762.         $valid_username = $this->is_valid_credentials( $settings );
  763.  
  764.         return $valid_username;
  765.     }
  766.  
  767.     /**
  768.      * Validate the credentials.
  769.      *
  770.      * @param array $settings The plugin settings.
  771.      *
  772.      * @return bool
  773.      */
  774.     public function is_valid_credentials( $settings ) {
  775.         $args = array( 'TRXTYPE' => 'A', 'TENDER' => 'C' );
  776.  
  777.         if ( ! empty( $settings ) ) {
  778.             $response = $this->post_to_payflow( $args, $settings );
  779.         }
  780.  
  781.         if ( ! empty( $response ) && $response['RESULT'] != '1' && $response['RESPMSG'] != 'User authentication failed' ) {
  782.             //$valid_username = true;
  783.             return true;
  784.         } else {
  785.             //$valid_username = false;
  786.             return false;
  787.         }
  788.  
  789.     }
  790.  
  791.     /**
  792.      * Helper to check if the vendor, partner and password settings are valid.
  793.      *
  794.      * @return bool
  795.      */
  796.     public function check_valid_api_credential_setting() {
  797.         global $valid_username;
  798.  
  799.         return $valid_username;
  800.     }
  801.  
  802.     /**
  803.      * Helper to check if the override vendor, partner and password settings are valid.
  804.      *
  805.      * @return bool
  806.      */
  807.     public function check_valid_override_credential_setting() {
  808.         global $valid_override_username;
  809.  
  810.         return $valid_override_username;
  811.     }
  812.  
  813.     /**
  814.      * Post to the Payflow API.
  815.      *
  816.      * @param array $nvp The transaction arguments.
  817.      * @param array $settings The plugin settings.
  818.      * @param null|int $form_id The ID of the current Form.
  819.      *
  820.      * @return array
  821.      */
  822.     public function post_to_payflow( $nvp = array(), $settings = array(), $form_id = null ) {
  823.         // Set up your API credentials and PayFlow Pro end point.
  824.         if ( ! empty( $settings ) ) {
  825.             $API_UserName = $settings['username'];
  826.             $API_Password = $settings['password'];
  827.             $Vendor       = $settings['vendor'];
  828.             $Vendor       = empty( $Vendor ) ? $API_UserName : $Vendor;
  829.             $Partner      = $settings['partner'];
  830.             $Partner      = empty( $Partner ) ? 'PayPal' : $Partner;
  831.             $mode         = $settings['mode'];
  832.  
  833.             $API_Endpoint = $mode == 'test' ? 'https://pilot-payflowpro.paypal.com' : 'https://payflowpro.paypal.com';
  834.  
  835.             $api_info = compact( 'API_Endpoint', 'API_UserName', 'API_Password', 'Vendor', 'Partner' );
  836.             $api_info = apply_filters( 'gform_paypalpaymentspro_api_before_send', $api_info, $form_id );
  837.             extract( $api_info );
  838.  
  839.             // Set the curl parameters.
  840.             $ch = curl_init();
  841.             curl_setopt( $ch, CURLOPT_URL, $API_Endpoint );
  842.             curl_setopt( $ch, CURLOPT_VERBOSE, 1 );
  843.             curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, false );
  844.             curl_setopt( $ch, CURLOPT_SSL_VERIFYHOST, false );
  845.             curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
  846.             curl_setopt( $ch, CURLOPT_POST, 1 );
  847.  
  848.             $nvp = apply_filters( 'gform_paypalpaymentspro_args_before_send', $nvp, $form_id );
  849.  
  850.             $nvpstr = '';
  851.             if ( is_array( $nvp ) ) {
  852.                 foreach ( $nvp as $key => $value ) {
  853.                     if ( is_array( $value ) ) {
  854.                         foreach ( $value as $item ) {
  855.                             if ( strlen( $nvpstr ) > 0 ) {
  856.                                 $nvpstr .= '&';
  857.                             }
  858.                             $nvpstr .= "$key=" . $item;
  859.                         }
  860.                     } else {
  861.                         if ( strlen( $nvpstr ) > 0 ) {
  862.                             $nvpstr .= '&';
  863.                         }
  864.                         $nvpstr .= "$key=" . $value;
  865.                     }
  866.                 }
  867.             }
  868.  
  869.             //add the bn code (build notation code)
  870.             $nvpstr = "BUTTONSOURCE=Rocketgenius_SP&$nvpstr";
  871.  
  872.             // Set the API operation, version, and API signature in the request.
  873.             $nvpreq = "VENDOR=$Vendor&PARTNER=$Partner&PWD=$API_Password&USER=$API_UserName&$nvpstr";
  874.  
  875.             $this->log_debug( __METHOD__ . "(): Sending request to PayPal - URL: {$API_Endpoint} Request: {$nvpreq}" );
  876.  
  877.             // Set the request as a POST FIELD for curl.
  878.             curl_setopt( $ch, CURLOPT_POSTFIELDS, $nvpreq );
  879.  
  880.             // Get response from the server.
  881.             $httpResponse = curl_exec( $ch );
  882.  
  883.             // Extract the response details.
  884.             $httpParsedResponseAr = array();
  885.             if ( $httpResponse ) {
  886.                 $httpResponseAr = explode( '&', $httpResponse );
  887.                 foreach ( $httpResponseAr as $i => $value ) {
  888.                     $tmpAr = explode( '=', urldecode( $value ) );
  889.                     if ( sizeof( $tmpAr ) > 1 ) {
  890.                         $httpParsedResponseAr[ $tmpAr[0] ] = $tmpAr[1];
  891.                     }
  892.                 }
  893.             }
  894.             $write_response_to_log = true;
  895.             if ( $nvp['TRXTYPE'] == 'A' && $httpParsedResponseAr['RESULT'] == '23' ) {
  896.                 $write_response_to_log = false;
  897.             }
  898.             if ( $write_response_to_log ) {
  899.                 $this->log_debug( __METHOD__ . '(): Response from PayPal: ' . $httpResponse );
  900.                 $this->log_debug( __METHOD__ . '(): Friendly view of response: ' . print_r( $httpParsedResponseAr, true ) );
  901.             }
  902.  
  903.             return $httpParsedResponseAr;
  904.         }
  905.     }
  906.  
  907.     /**
  908.      * Prepare the transaction arguments.
  909.      *
  910.      * @param array $feed The feed object currently being processed.
  911.      * @param array $submission_data The customer and transaction data.
  912.      * @param array $form The form object currently being processed.
  913.      * @param array $entry The entry object currently being processed.
  914.      *
  915.      * @return array
  916.      */
  917.     public function prepare_credit_card_transaction( $feed, $submission_data, $form, $entry ) {
  918.  
  919.         // Billing Information
  920.         $card_number     = $submission_data['card_number'];
  921.         $expiration_date = str_pad( $submission_data['card_expiration_date'][0], 2, '0', STR_PAD_LEFT ) . substr( $submission_data['card_expiration_date'][1], - 2 );; // ?? correct format ??
  922.         $country               = $submission_data['country'];
  923.         $country               = GFCommon::get_country_code( $country );
  924.         $args                  = array();
  925.         $args['ACCT']          = $card_number;
  926.         $args['EXPDATE']       = $expiration_date;
  927.         $args['CVV2']          = $submission_data['card_security_code'];
  928.         $args['STREET']        = $submission_data['address'];
  929.         $args['BILLTOSTREET2'] = $submission_data['address2'];
  930.         $args['CITY']          = $submission_data['city'];
  931.         $args['STATE']         = $submission_data['state'];
  932.         $args['ZIP']           = $submission_data['zip'];
  933.         $args['BILLTOCOUNTRY'] = $country == 'UK' ? 'GB' : $country;
  934.         $args['CURRENCY']      = GFCommon::get_currency();
  935.  
  936.         // Customer Information
  937.         $args['FIRSTNAME'] = $submission_data['firstName'];
  938.         $args['LASTNAME']  = $submission_data['lastName'];
  939.         $args['EMAIL']     = $submission_data['email'];
  940.  
  941.         // Product Information
  942.         $i            = 0;
  943.         $args['DESC'] = '';
  944.         foreach ( $submission_data['line_items'] as $line_item ) {
  945.             if ( $feed['meta']['transactionType'] == 'product' ) {
  946.                 $args["L_NAME$i"]   = $line_item['name'];
  947.                 $args["L_DESC$i"]   = $line_item['description'];
  948.                 $args["L_AMT$i"]    = $line_item['unit_price'];
  949.                 $args["L_NUMBER$i"] = $i + 1;
  950.                 $args["L_QTY$i"]    = $line_item['quantity'];
  951.             } else {
  952.                 $args['DESC'] .= $i > 1 ? ', ' . $line_item['name'] : $line_item['name']; // ?? TO DO figure out why there is warning that desc is undefined
  953.             }
  954.             $i ++;
  955.  
  956.         }
  957.  
  958.         $args['AMT']    = $submission_data['payment_amount'];
  959.         $args['TENDER'] = 'C';
  960.  
  961.         return $args;
  962.     }
  963.  
  964.     /**
  965.      * Prepare the appropriate error message for the transaction result.
  966.      *
  967.      * @param array $response The response from the Payflow API.
  968.      *
  969.      * @return string
  970.      */
  971.     public function get_error_message( $response ) {
  972.         $code = $response['RESULT'];
  973.  
  974.         switch ( $code ) {
  975.             case '50' :
  976.                 $message = esc_html__( 'This credit card has been declined by your bank. Please use another form of payment.', 'gravityformspaypalpaymentspro' );
  977.                 break;
  978.  
  979.             case '24' :
  980.                 $message = esc_html__( 'The credit card has expired.', 'gravityformspaypalpaymentspro' );
  981.                 break;
  982.  
  983.             case '1021' :
  984.                 $message = esc_html__( 'The merchant does not accept this type of credit card.', 'gravityformspaypalpaymentspro' );
  985.                 break;
  986.  
  987.             case "12" :
  988.             case "23" :
  989.                 $message = esc_html__( 'There was an error processing your credit card. Please verify the information and try again.', 'gravityformspaypalpaymentspro' );
  990.                 break;
  991.  
  992.             default :
  993.                 $message = esc_html__( 'There was an error processing your request. Your credit card was not charged. Please try again.', 'gravityformspaypalpaymentspro' );
  994.         }
  995.  
  996.         $message = '<!-- Error: ' . $code . ' -->' . $message;
  997.  
  998.         return $message;
  999.     }
  1000.  
  1001.     /**
  1002.      * Convert feed into config for hooks backwards compatibility.
  1003.      *
  1004.      * @param array $feed The current feed object.
  1005.      * @param array $submission_data The customer and transaction data.
  1006.      *
  1007.      * @return array
  1008.      */
  1009.     private function get_config( $feed, $submission_data ) {
  1010.  
  1011.         $config = array();
  1012.  
  1013.         $config['id']        = $feed['id'];
  1014.         $config['form_id']   = $feed['form_id'];
  1015.         $config['is_active'] = $feed['is_active'];
  1016.  
  1017.         $config['meta']['type']               = rgar( $feed['meta'], 'transactionType' );
  1018.         $config['meta']['update_post_action'] = rgar( $feed['meta'], 'update_post_action' );
  1019.  
  1020.         $config['meta']['paypalpaymentspro_conditional_enabled'] = rgar( $feed['meta'], 'feed_condition_conditional_logic' );
  1021.         if ( $feed['meta']['feed_condition_conditional_logic'] ) {
  1022.             $config['meta']['paypalpaymentspro_conditional_field_id'] = $feed['meta']['feed_condition_conditional_logic_object']['conditionalLogic']['rules'][0]['fieldId'];
  1023.             $config['meta']['paypalpaymentspro_conditional_operator'] = $feed['meta']['feed_condition_conditional_logic_object']['conditionalLogic']['rules'][0]['operator'];
  1024.             $config['meta']['paypalpaymentspro_conditional_value']    = $feed['meta']['feed_condition_conditional_logic_object']['conditionalLogic']['rules'][0]['value'];
  1025.         }
  1026.  
  1027.         $config['meta']['api_settings_enabled'] = rgar( $feed['meta'], 'apiSettingsEnabled' );
  1028.         $config['meta']['api_mode']             = rgar( $feed['meta'], 'overrideMode' );
  1029.         $config['meta']['api_username']         = rgar( $feed['meta'], 'overrideUsername' );
  1030.         $config['meta']['api_password']         = rgar( $feed['meta'], 'overridePassword' );
  1031.         $config['meta']['api_vendor']           = rgar( $feed['meta'], 'overrideVendor' );
  1032.         $config['meta']['api_partner']          = rgar( $feed['meta'], 'overridePartner' );
  1033.  
  1034.         $config['meta']['customer_fields']['email']    = rgar( $feed['meta'], 'billingInformation_email' );
  1035.         $config['meta']['customer_fields']['address1'] = rgar( $feed['meta'], 'billingInformation_address' );
  1036.         $config['meta']['customer_fields']['address2'] = rgar( $feed['meta'], 'billingInformation_address2' );
  1037.         $config['meta']['customer_fields']['city']     = rgar( $feed['meta'], 'billingInformation_city' );
  1038.         $config['meta']['customer_fields']['state']    = rgar( $feed['meta'], 'billingInformation_state' );
  1039.         $config['meta']['customer_fields']['zip']      = rgar( $feed['meta'], 'billingInformation_zip' );
  1040.         $config['meta']['customer_fields']['country']  = rgar( $feed['meta'], 'billingInformation_country' );
  1041.  
  1042.         return $config;
  1043.  
  1044.     }
  1045.  
  1046.  
  1047.     // # TO FRAMEWORK MIGRATION ----------------------------------------------------------------------------------------
  1048.  
  1049.     /**
  1050.      * Initialize the admin specific hooks.
  1051.      */
  1052.     public function init_admin() {
  1053.         parent::init_admin();
  1054.  
  1055.         add_filter( 'gform_addon_navigation', array( $this, 'maybe_create_menu' ) );
  1056.     }
  1057.  
  1058.     /**
  1059.      * Maybe add the temporary plugin page to the menu.
  1060.      *
  1061.      * @param array $menus
  1062.      *
  1063.      * @return array
  1064.      */
  1065.     public function maybe_create_menu( $menus ) {
  1066.  
  1067.         $current_user                   = wp_get_current_user();
  1068.         $dismiss_paypalpaymentspro_menu = get_metadata( 'user', $current_user->ID, 'dismiss_paypalpaymentspro_menu', true );
  1069.         if ( $dismiss_paypalpaymentspro_menu != '1' ) {
  1070.             $menus[] = array( 'name'       => $this->_slug,
  1071.                               'label'      => $this->get_short_title(),
  1072.                               'callback'   => array( $this, 'temporary_plugin_page' ),
  1073.                               'permission' => $this->_capabilities_form_settings
  1074.             );
  1075.         }
  1076.  
  1077.         return $menus;
  1078.     }
  1079.  
  1080.     /**
  1081.      * Initialize the AJAX hooks.
  1082.      */
  1083.     public function init_ajax() {
  1084.         parent::init_ajax();
  1085.  
  1086.         add_action( 'wp_ajax_gf_dismiss_paypalpaymentspro_menu', array( $this, 'ajax_dismiss_menu' ) );
  1087.     }
  1088.  
  1089.     /**
  1090.      * Update the user meta to indicate they shouldn't see the temporary plugin page again.
  1091.      */
  1092.     public function ajax_dismiss_menu() {
  1093.  
  1094.         $current_user = wp_get_current_user();
  1095.         update_metadata( 'user', $current_user->ID, 'dismiss_paypalpaymentspro_menu', '1' );
  1096.     }
  1097.  
  1098.     /**
  1099.      * Display a temporary page explaining how feeds are now managed.
  1100.      */
  1101.     public function temporary_plugin_page() {
  1102.         ?>
  1103.         <script type="text/javascript">
  1104.             function dismissMenu() {
  1105.                 jQuery('#gf_spinner').show();
  1106.                 jQuery.post(ajaxurl, {
  1107.                             action: "gf_dismiss_paypalpaymentspro_menu"
  1108.                         },
  1109.                         function (response) {
  1110.                             document.location.href = '?page=gf_edit_forms';
  1111.                             jQuery('#gf_spinner').hide();
  1112.                         }
  1113.                 );
  1114.  
  1115.             }
  1116.         </script>
  1117.  
  1118.         <div class="wrap about-wrap">
  1119.             <h1><?php esc_html_e( 'PayPal Payments Pro Add-On v2.0', 'gravityformspaypalpaymentspro' ) ?></h1>
  1120.  
  1121.             <div class="about-text"><?php esc_html_e( 'Thank you for updating! The new version of the Gravity Forms PayPal Payments Pro Add-On makes changes to how you manage your PayPal Payments Pro integration.', 'gravityformspaypalpaymentspro' ) ?></div>
  1122.             <div class="changelog">
  1123.                 <hr/>
  1124.                 <div class="feature-section col two-col">
  1125.                     <div class="col-1">
  1126.                         <h3><?php esc_html_e( 'Manage PayPal Payments Pro Contextually', 'gravityformspaypalpaymentspro' ) ?></h3>
  1127.  
  1128.                         <p><?php esc_html_e( 'PayPal Payments Pro Feeds are now accessed via the PayPal Payments Pro sub-menu within the Form Settings for the Form with which you would like to integrate PayPal Payments Pro.', 'gravityformspaypalpaymentspro' ) ?></p>
  1129.                     </div>
  1130.                     <div class="col-2 last-feature">
  1131.                         <img src="http://gravityforms.s3.amazonaws.com/webimages/AddonNotice/NewPayPalPaymentsPro2.png">
  1132.                     </div>
  1133.                 </div>
  1134.  
  1135.                 <hr/>
  1136.  
  1137.                 <form method="post" id="dismiss_menu_form" style="margin-top: 20px;">
  1138.                     <input type="checkbox" name="dismiss_paypalpaymentspro_menu" value="1" onclick="dismissMenu();">
  1139.                     <label><?php esc_html_e( 'I understand this change, dismiss this message!', 'gravityformspaypalpaymentspro' ) ?></label>
  1140.                     <img id="gf_spinner" src="<?php echo GFCommon::get_base_url() . '/images/spinner.gif' ?>" alt="<?php esc_html_e( 'Please wait...', 'gravityformspaypalpaymentspro' ) ?>" style="display:none;"/>
  1141.                 </form>
  1142.  
  1143.             </div>
  1144.         </div>
  1145.         <?php
  1146.     }
  1147.  
  1148.     /**
  1149.      * Checks if a previous version was installed and if the feeds need migrating to the framework structure.
  1150.      *
  1151.      * @param string $previous_version The version number of the previously installed version.
  1152.      */
  1153.     public function upgrade( $previous_version ) {
  1154.         if ( empty( $previous_version ) ) {
  1155.             $previous_version = get_option( 'gf_paypalpaymentspro_version' );
  1156.         }
  1157.         $previous_is_pre_addon_framework = ! empty( $previous_version ) && version_compare( $previous_version, '2.0.dev1', '<' );
  1158.  
  1159.         if ( $previous_is_pre_addon_framework ) {
  1160.             $this->log_debug( __METHOD__ . '(): Copying over data to new table structure.' );
  1161.             $old_feeds = $this->get_old_feeds();
  1162.  
  1163.             if ( ! $old_feeds ) {
  1164.                 $this->log_debug( __METHOD__ . '(): No old feeds found to copy.' );
  1165.  
  1166.                 return;
  1167.             }
  1168.  
  1169.             $counter = 1;
  1170.             foreach ( $old_feeds as $old_feed ) {
  1171.                 $feed_name       = 'Feed ' . $counter;
  1172.                 $form_id         = $old_feed['form_id'];
  1173.                 $is_active       = $old_feed['is_active'];
  1174.                 $customer_fields = rgar( $old_feed['meta'], 'customer_fields' );
  1175.  
  1176.                 $new_meta = array(
  1177.                         'feedName'           => $feed_name,
  1178.                         'transactionType'    => rgar( $old_feed['meta'], 'type' ),
  1179.                         'change_post_status' => rgar( $old_feed['meta'], 'update_post_action' ) ? '1' : '0',
  1180.                         'update_post_action' => rgar( $old_feed['meta'], 'update_post_action' ),
  1181.                         'recurringAmount'    => rgar( $old_feed['meta'], 'recurring_amount_field' ) == 'all' ? 'form_total' : rgar( $old_feed['meta'], 'recurring_amount_field' ),
  1182.                         'recurringTimes'     => rgar( $old_feed['meta'], 'recurring_times' ),
  1183.                         'payPeriod'          => rgar( $old_feed['meta'], 'pay_period' ),
  1184.                         'paymentAmount'      => 'form_total', //default to this for new field in framework version
  1185.                         'setupFee_enabled'   => rgar( $old_feed['meta'], 'setup_fee_enabled' ),
  1186.                         'setupFee_product'   => rgar( $old_feed['meta'], 'setup_fee_amount_field' ),
  1187.  
  1188.                         'billingInformation_firstName' => rgar( $customer_fields, 'first_name' ),
  1189.                         'billingInformation_lastName'  => rgar( $customer_fields, 'last_name' ),
  1190.                         'billingInformation_email'     => rgar( $customer_fields, 'email' ),
  1191.                         'billingInformation_address'   => rgar( $customer_fields, 'address1' ),
  1192.                         'billingInformation_address2'  => rgar( $customer_fields, 'address2' ),
  1193.                         'billingInformation_city'      => rgar( $customer_fields, 'city' ),
  1194.                         'billingInformation_state'     => rgar( $customer_fields, 'state' ),
  1195.                         'billingInformation_zip'       => rgar( $customer_fields, 'zip' ),
  1196.                         'billingInformation_country'   => rgar( $customer_fields, 'country' ),
  1197.  
  1198.                         'apiSettingsEnabled' => rgar( $old_feed['meta'], 'api_settings_enabled' ),
  1199.                         'overrideMode'       => rgar( $old_feed['meta'], 'api_mode' ),
  1200.                         'overrideUsername'   => rgar( $old_feed['meta'], 'api_username' ),
  1201.                         'overridePassword'   => rgar( $old_feed['meta'], 'api_password' ),
  1202.                         'overrideVendor'     => rgar( $old_feed['meta'], 'api_vendor' ),
  1203.                         'overridePartner'    => rgar( $old_feed['meta'], 'api_partner' ),
  1204.                 );
  1205.  
  1206.                 $optin_enabled = rgar( $old_feed['meta'], 'paypalpaymentspro_conditional_enabled' );
  1207.                 if ( $optin_enabled ) {
  1208.                     $new_meta['feed_condition_conditional_logic']        = 1;
  1209.                     $new_meta['feed_condition_conditional_logic_object'] = array(
  1210.                             'conditionalLogic' => array(
  1211.                                     'actionType' => 'show',
  1212.                                     'logicType'  => 'all',
  1213.                                     'rules'      => array(
  1214.                                             array(
  1215.                                                     'fieldId'  => $old_feed['meta']['paypalpaymentspro_conditional_field_id'],
  1216.                                                     'operator' => $old_feed['meta']['paypalpaymentspro_conditional_operator'],
  1217.                                                     'value'    => $old_feed['meta']['paypalpaymentspro_conditional_value'],
  1218.                                             ),
  1219.                                     )
  1220.                             )
  1221.                     );
  1222.                 } else {
  1223.                     $new_meta['feed_condition_conditional_logic'] = 0;
  1224.                 }
  1225.  
  1226.                 $this->insert_feed( $form_id, $is_active, $new_meta );
  1227.                 $counter ++;
  1228.  
  1229.             }
  1230.  
  1231.             $old_settings = get_option( 'gf_paypalpaymentspro_settings' );
  1232.  
  1233.             if ( ! empty( $old_settings ) ) {
  1234.                 $this->log_debug( __METHOD__ . '(): Copying plugin settings.' );
  1235.                 $new_settings = array(
  1236.                         'mode'     => rgar( $old_settings, 'mode' ),
  1237.                         'username' => rgar( $old_settings, 'username' ),
  1238.                         'password' => rgar( $old_settings, 'password' ),
  1239.                         'vendor'   => rgar( $old_settings, 'vendor' ),
  1240.                         'partner'  => rgar( $old_settings, 'partner' ),
  1241.                 );
  1242.  
  1243.                 parent::update_plugin_settings( $new_settings );
  1244.             }
  1245.  
  1246.             //copy existing transactions to new table
  1247.             $this->copy_transactions();
  1248.  
  1249.         }
  1250.  
  1251.     }
  1252.  
  1253.     /**
  1254.      * Retrieve any old feeds which need migrating to the framework,
  1255.      *
  1256.      * @return bool|array
  1257.      */
  1258.     public function get_old_feeds() {
  1259.         global $wpdb;
  1260.         $table_name = $wpdb->prefix . 'rg_paypalpaymentspro';
  1261.  
  1262.         if ( ! $this->table_exists( $table_name ) ) {
  1263.             return false;
  1264.         }
  1265.  
  1266.         $form_table_name = GFFormsModel::get_form_table_name();
  1267.         $sql             = "SELECT s.id, s.is_active, s.form_id, s.meta, f.title as form_title
  1268.                     FROM {$table_name} s
  1269.                     INNER JOIN {$form_table_name} f ON s.form_id = f.id";
  1270.  
  1271.         $results = $wpdb->get_results( $sql, ARRAY_A );
  1272.  
  1273.         $count = sizeof( $results );
  1274.  
  1275.         $this->log_debug( __METHOD__ . '(): ' . $count . ' feed(s) found to copy.' );
  1276.  
  1277.         for ( $i = 0; $i < $count; $i ++ ) {
  1278.             $results[ $i ]['meta'] = maybe_unserialize( $results[ $i ]['meta'] );
  1279.         }
  1280.  
  1281.         return $results;
  1282.     }
  1283.  
  1284.     /**
  1285.      * Copy transactions from the old add-on table to the framework table.
  1286.      *
  1287.      * @return bool
  1288.      */
  1289.     public function copy_transactions() {
  1290.         global $wpdb;
  1291.         $old_table_name = $this->get_old_transaction_table_name();
  1292.         if ( ! $this->table_exists( $old_table_name ) ) {
  1293.             return false;
  1294.         }
  1295.         $this->log_debug( __METHOD__ . '(): Copying old PayPal Payments Pro transactions into new table structure.' );
  1296.  
  1297.         $new_table_name = $this->get_new_transaction_table_name();
  1298.  
  1299.         $sql = "INSERT INTO {$new_table_name} (lead_id, transaction_type, transaction_id, is_recurring, amount, date_created)
  1300.                     SELECT entry_id, transaction_type, transaction_id, is_renewal, amount, date_created FROM {$old_table_name}";
  1301.  
  1302.         $wpdb->query( $sql );
  1303.  
  1304.         $this->log_debug( __METHOD__ . "(): transactions: {$wpdb->rows_affected} rows were added." );
  1305.     }
  1306.  
  1307.     /**
  1308.      * Returns the name of the old table used to store transactions.
  1309.      *
  1310.      * @return string
  1311.      */
  1312.     public function get_old_transaction_table_name() {
  1313.         global $wpdb;
  1314.  
  1315.         return $wpdb->prefix . 'rg_paypalpaymentspro_transaction';
  1316.     }
  1317.  
  1318.     /**
  1319.      * Returns the name of the framework table used to store transactions.
  1320.      *
  1321.      * @return string
  1322.      */
  1323.     public function get_new_transaction_table_name() {
  1324.         global $wpdb;
  1325.  
  1326.         return $wpdb->prefix . 'gf_addon_payment_transaction';
  1327.     }
  1328.  
  1329. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement