/** * Helper function to determine whether a plugin is active * * @since 2.0.0 * @param string $plugin_name plugin name, as the plugin-filename.php * @return boolean true if the named plugin is installed and active */ public function is_plugin_active($plugin_name) { $active_plugins = (array) get_option('active_plugins', array()); if (is_multisite()) { $active_plugins = array_merge($active_plugins, array_keys(get_site_option('active_sitewide_plugins', array()))); } $plugin_filenames = array(); foreach ($active_plugins as $plugin) { if (SV_WC_Helper::str_exists($plugin, '/')) { // normal plugin name (plugin-dir/plugin-filename.php) list(, $filename) = explode('/', $plugin); } else { // no directory, just plugin file $filename = $plugin; } $plugin_filenames[] = $filename; } return in_array($plugin_name, $plugin_filenames); }
/** * Upgrade to the currently installed version * * @since 2.0.0 * @param string $installed_version currently installed version */ public function upgrade($installed_version) { // upgrade to 2.0.0 if (version_compare($installed_version, '2.0.0', '<')) { $this->log('Starting upgrade to 2.0.0'); /** Upgrade settings */ $old_cc_settings = get_option('woocommerce_authorize_net_cim_settings'); $old_echeck_settings = get_option('woocommerce_authorize_net_cim_echeck_settings'); if ($old_cc_settings) { // prior to 2.0.0, there was no settings for tokenization (always on) and enable_customer_decline_messages. // eCheck settings were inherited from the credit card gateway by default // credit card $new_cc_settings = array('enabled' => isset($old_cc_settings['enabled']) && 'yes' === $old_cc_settings['enabled'] ? 'yes' : 'no', 'title' => !empty($old_cc_settings['title']) ? $old_cc_settings['title'] : 'Credit Card', 'description' => !empty($old_cc_settings['description']) ? $old_cc_settings['description'] : 'Pay securely using your credit card.', 'enable_csc' => isset($old_cc_settings['require_cvv']) && 'yes' === $old_cc_settings['require_cvv'] ? 'yes' : 'no', 'transaction_type' => isset($old_cc_settings['transaction_type']) && 'auth_capture' === $old_cc_settings['transaction_type'] ? 'charge' : 'authorization', 'card_types' => !empty($old_cc_settings['card_types']) ? $old_cc_settings['card_types'] : array('VISA', 'MC', 'AMEX', 'DISC'), 'tokenization' => 'yes', 'environment' => isset($old_cc_settings['test_mode']) && 'yes' === $old_cc_settings['test_mode'] ? 'test' : 'production', 'inherit_settings' => 'no', 'api_login_id' => !empty($old_cc_settings['api_login_id']) ? $old_cc_settings['api_login_id'] : '', 'api_transaction_key' => !empty($old_cc_settings['api_transaction_key']) ? $old_cc_settings['api_transaction_key'] : '', 'test_api_login_id' => !empty($old_cc_settings['test_api_login_id']) ? $old_cc_settings['test_api_login_id'] : '', 'test_api_transaction_key' => !empty($old_cc_settings['test_api_transaction_key']) ? $old_cc_settings['test_api_transaction_key'] : '', 'enable_customer_decline_messages' => 'no', 'debug_mode' => !empty($old_cc_settings['debug_mode']) ? $old_cc_settings['debug_mode'] : 'off'); // eCheck $new_echeck_settings = array('enabled' => isset($old_echeck_settings['enabled']) && 'yes' === $old_echeck_settings['enabled'] ? 'yes' : 'no', 'title' => !empty($old_echeck_settings['title']) ? $old_echeck_settings['title'] : 'eCheck', 'description' => !empty($old_echeck_settings['description']) ? $old_echeck_settings['description'] : 'Pay securely using your checking account.', 'tokenization' => 'yes', 'environment' => $new_cc_settings['environment'], 'inherit_settings' => 'yes', 'api_login_id' => '', 'api_transaction_key' => '', 'test_api_login_id' => '', 'test_api_transaction_key' => '', 'enable_customer_decline_messages' => 'no', 'debug_mode' => $new_cc_settings['debug_mode']); // save new settings, remove old ones update_option('woocommerce_authorize_net_cim_credit_card_settings', $new_cc_settings); update_option('woocommerce_authorize_net_cim_echeck_settings', $new_echeck_settings); delete_option('woocommerce_authorize_net_cim_settings'); $this->log('Settings upgraded.'); } /** Update meta key for customer profile ID and shipping profile ID */ global $wpdb; // old key: _wc_authorize_net_cim_profile_id // new key: wc_authorize_net_cim_customer_profile_id // note that we don't know on a per-user basis what environment the customer ID was set in, so we assume production, just to be safe $rows = $wpdb->update($wpdb->usermeta, array('meta_key' => 'wc_authorize_net_cim_customer_profile_id'), array('meta_key' => '_wc_authorize_net_cim_profile_id')); $this->log(sprintf('%d users updated for customer profile ID.', $rows)); // old key: _wc_authorize_net_cim_shipping_profile_id // new key: wc_authorize_net_cim_shipping_address_id $rows = $wpdb->update($wpdb->usermeta, array('meta_key' => 'wc_authorize_net_cim_shipping_address_id'), array('meta_key' => '_wc_authorize_net_cim_shipping_profile_id')); $this->log(sprintf('%d users updated for shipping address ID', $rows)); /** Update meta values for order payment method & recurring payment method */ // meta key: _payment_method // old value: authorize_net_cim // new value: authorize_net_cim_credit_card // note that the eCheck method has not changed from 1.x to 2.x $rows = $wpdb->update($wpdb->postmeta, array('meta_value' => 'authorize_net_cim_credit_card'), array('meta_key' => '_payment_method', 'meta_value' => 'authorize_net_cim')); $this->log(sprintf('%d orders updated for payment method meta', $rows)); // meta key: _recurring_payment_method // old value: authorize_net_cim // new value: authorize_net_cim_credit_card $rows = $wpdb->update($wpdb->postmeta, array('meta_value' => 'authorize_net_cim_credit_card'), array('meta_key' => '_recurring_payment_method', 'meta_value' => 'authorize_net_cim')); $this->log(sprintf('%d orders updated for recurring payment method meta', $rows)); /** Convert payment profiles stored in legacy format to framework payment token format */ $this->log('Starting payment profile upgrade.'); $user_ids = $wpdb->get_col("SELECT user_id FROM {$wpdb->usermeta} WHERE meta_key = '_wc_authorize_net_cim_payment_profiles'"); if ($user_ids) { // iterate through each user with a payment profile foreach ($user_ids as $user_id) { $customer_profile_id = get_user_meta($user_id, 'wc_authorize_net_cim_customer_profile_id', true); $payment_profiles = get_user_meta($user_id, '_wc_authorize_net_cim_payment_profiles', true); $cc_tokens = $echeck_tokens = array(); // iterate through each payment profile foreach ($payment_profiles as $profile_id => $profile) { // bail if corrupted if (!$profile_id || empty($profile['type'])) { continue; } // parse expiry date if (!empty($profile['exp_date']) && SV_WC_Helper::str_exists($profile['exp_date'], '/')) { list($exp_month, $exp_year) = explode('/', $profile['exp_date']); } else { $exp_month = $exp_year = ''; } if ('Bank Account' === $profile['type']) { // eCheck tokens $echeck_tokens[$profile_id] = array('type' => 'echeck', 'last_four' => !empty($profile['last_four']) ? $profile['last_four'] : '', 'customer_profile_id' => $customer_profile_id, 'billing_hash' => '', 'payment_hash' => '', 'default' => !empty($profile['active']) && $profile['active'], 'exp_month' => $exp_month, 'exp_year' => $exp_year); } else { // parse card type switch ($profile['type']) { case 'Visa': $card_type = 'visa'; break; case 'American Express': $card_type = 'amex'; break; case 'MasterCard': $card_type = 'mc'; break; case 'Discover': $card_type = 'disc'; break; case 'Diners Club': $card_type = 'diners'; break; case 'JCB': $card_type = 'jcb'; break; default: $card_type = ''; } // credit card tokens $cc_tokens[$profile_id] = array('type' => 'credit_card', 'last_four' => !empty($profile['last_four']) ? $profile['last_four'] : '', 'customer_profile_id' => $customer_profile_id, 'billing_hash' => '', 'payment_hash' => '', 'default' => !empty($profile['active']) && $profile['active'], 'card_type' => $card_type, 'exp_month' => $exp_month, 'exp_year' => $exp_year); } } // update credit card tokens if (!empty($cc_tokens)) { update_user_meta($user_id, '_wc_authorize_net_cim_credit_card_payment_tokens', $cc_tokens); } // update eCheck tokens if (!empty($echeck_tokens)) { update_user_meta($user_id, '_wc_authorize_net_cim_echeck_payment_tokens', $echeck_tokens); } // save the legacy payment profiles in case we need them later update_user_meta($user_id, '_wc_authorize_net_cim_legacy_tokens', $payment_profiles); delete_user_meta($user_id, '_wc_authorize_net_cim_payment_profiles'); $this->log(sprintf('Converted payment profile for user ID: %s', $user_id)); } } $this->log('Completed payment profile upgrade.'); $this->log('Completed upgrade for 2.0.0'); } // TODO: remove _wc_authorize_net_cim_legacy_tokens meta in a future version @MR 2015-07 }
/** * Correctly format a credit card expiration date for storage. * * @since 4.3.0 * @param array $data * @return array */ protected function prepare_expiry_date($data) { // expiry date must be present, include a forward slash and be 5 characters (MM/YY) if (!$data['expiry'] || !SV_WC_Helper::str_exists($data['expiry'], '/') || 5 !== strlen($data['expiry'])) { unset($data['expiry']); return $data; } list($data['exp_month'], $data['exp_year']) = explode('/', $data['expiry']); unset($data['expiry']); return $data; }
/** * Parse taxonomy & terms from a key and its values * * @since 3.0.0 * @param string $key * @param string $value * @return array|null Array with parsed taxonomy name and it's terms, or null on failure */ protected function parse_taxonomy_terms($key, $value) { // get taxonomy $taxonomy = trim(str_replace('tax:', '', $key)); // exists? if (!taxonomy_exists($taxonomy)) { wc_csv_import_suite()->log(sprintf(__('> > Skipping taxonomy "%s" - it does not exist.', 'woocommerce-csv-import-suite'), $taxonomy)); return null; } // get terms - ID => parent $terms = array(); $raw_terms = explode('|', $value); $raw_terms = array_map('trim', $raw_terms); // handle term hierachy (>) foreach ($raw_terms as $raw_term) { if (SV_WC_Helper::str_exists($raw_term, '>')) { $raw_term = explode('>', $raw_term); $raw_term = array_map('trim', $raw_term); $raw_term = array_map('esc_html', $raw_term); $raw_term = array_filter($raw_term); $parent = 0; $loop = 0; foreach ($raw_term as $term) { $loop++; $term_id = ''; if (isset($this->inserted_terms[$taxonomy][$parent][$term])) { $term_id = $this->inserted_terms[$taxonomy][$parent][$term]; } elseif ($term) { // check term existance $term_may_exist = term_exists($term, $taxonomy, absint($parent)); if (is_array($term_may_exist)) { $possible_term = get_term($term_may_exist['term_id'], $taxonomy); if ($possible_term->parent == $parent) { $term_id = $term_may_exist['term_id']; } } if (!$term_id) { // create appropriate slug $slug = array(); for ($i = 0; $i < $loop; $i++) { $slug[] = $raw_term[$i]; } $slug = sanitize_title(implode('-', $slug)); $t = wp_insert_term($term, $taxonomy, array('parent' => $parent, 'slug' => $slug)); if (!is_wp_error($t)) { $term_id = $t['term_id']; } else { wc_csv_import_suite()->log(sprintf(__('> > (' . $this->line_num . ') Failed to import term %s, parent %s - %s', 'woocommerce-csv-import-suite'), sanitize_text_field($term), sanitize_text_field($parent), sanitize_text_field($taxonomy))); break; } } $this->inserted_terms[$taxonomy][$parent][$term] = $term_id; } if (!$term_id) { break; } // sdd to terms, ready to set if this is the final term if (sizeof($raw_term) == $loop) { $terms[] = $term_id; } $parent = $term_id; } } else { $term_id = ''; $raw_term = esc_html($raw_term); if (isset($this->inserted_terms[$taxonomy][0][$raw_term])) { $term_id = $this->inserted_terms[$taxonomy][0][$raw_term]; } elseif ($raw_term) { // Check term existance $term_exists = term_exists($raw_term, $taxonomy, 0); $term_id = is_array($term_exists) ? $term_exists['term_id'] : 0; if (!$term_id) { $t = wp_insert_term(trim($raw_term), $taxonomy, array('parent' => 0)); if (!is_wp_error($t)) { $term_id = $t['term_id']; } else { wc_csv_import_suite()->log(sprintf(__('> > Failed to import term %s %s', 'woocommerce-csv-import-suite'), esc_html($raw_term), esc_html($taxonomy))); break; } } $this->inserted_terms[$taxonomy][0][$raw_term] = $term_id; } // store terms for later insertion if ($term_id) { $terms[] = $term_id; } } } return !empty($terms) ? array($taxonomy, $terms) : null; }
/** * Wrapper around perform_request() to catch specific errors resulting from * transaction requests that can be transparently handled: * * 1) If a local shipping address no longer exists in CIM, it will be removed * after the failed transaction request. The user can retry the transaction * and a new shipping address will be created. * * @since 2.0.0 * @param \WC_Authorize_Net_CIM_API_Request $request * @param \WC_Order $order order * @return \WC_Authorize_Net_CIM_API_Response Authorize.Net API response object * @throws \SV_WC_API_Exception */ protected function perform_transaction($request, WC_Order $order) { $this->order = $order; try { return $this->perform_request($request); } catch (SV_WC_API_Exception $e) { // record not found if (40 == $e->getCode()) { if (SV_WC_Helper::str_exists($e->getMessage(), 'Customer Shipping Address ID')) { // shipping address not found, remove it locally $shipping = $this->get_gateway()->get_shipping_address($order->get_user_id()); $shipping->delete(); } } } throw $e; }