diff --git a/config.php b/config.php
index b2eced1..4cf886c 100644
--- a/config.php
+++ b/config.php
@@ -22,8 +22,8 @@
define( 'WP_FSM__MAIN_ENDPOINT', 'fs-api' );
}
- if ( ! defined( 'WP_FS__NAMESPACE_EDD' ) ) {
- define( 'WP_FS__NAMESPACE_EDD', 'EDD' );
+ if ( ! defined( 'WP_FS__NAMESPACE_WC' ) ) {
+ define( 'WP_FS__NAMESPACE_WC', 'wc' );
}
if ( ! defined( 'WP_FS__IS_PRODUCTION_MODE' ) ) {
diff --git a/freemius-edd-migration.php b/freemius-wc-migration.php
similarity index 50%
rename from freemius-edd-migration.php
rename to freemius-wc-migration.php
index ac9d004..efd57c8 100644
--- a/freemius-edd-migration.php
+++ b/freemius-wc-migration.php
@@ -1,15 +1,15 @@
true )
);
@@ -36,31 +34,28 @@ function fs_edd_migration_init() {
require_once __DIR__ . '/start.php';
// Load migration module.
- require_once WP_FSM__DIR_MIGRATION . '/edd/class-fs-edd-migration-endpoint.php';
+ require_once WP_FSM__DIR_MIGRATION . '/wc/class-fs-wc-migration-endpoint.php';
}
- // Get Freemius EDD Migration running.
- add_action( 'plugins_loaded', 'fs_edd_migration_init' );
+ // Get Freemius WC Migration running.
+ add_action( 'plugins_loaded', 'fs_wc_migration_init' );
- function fs_edd_migration_auto_redirect() {
+ function fs_wc_migration_auto_redirect() {
if ( ! function_exists( 'is_network_admin' ) || ! is_network_admin() ) {
- if ( 'true' === get_option( 'fs_edd_migration_activated' ) ) {
+ if ( 'true' === get_option( 'fs_wc_migration_activated' ) ) {
// Load config.
require_once __DIR__ . '/start.php';
- update_option( 'fs_edd_migration_activated', null );
+ update_option( 'fs_wc_migration_activated', null );
- if ( fs_redirect( add_query_arg( array(
- 'post_type' => 'download',
- 'page' => 'fs-migration',
- ), admin_url( 'edit.php', 'admin' ) ) ) ) {
+ if ( fs_redirect( admin_url( 'admin.php?page=fs-migration' ) ) ) {
exit;
}
}
}
}
- add_action( 'admin_init', 'fs_edd_migration_auto_redirect' );
+ add_action( 'admin_init', 'fs_wc_migration_auto_redirect' );
function fs_migration_plugin_activation() {
require_once __DIR__ . '/includes/class-fs-entity-mapper.php';
@@ -69,7 +64,7 @@ function fs_migration_plugin_activation() {
FS_Entity_Mapper::create_table();
// Hint the plugin that it was just activated.
- update_option( "fs_edd_migration_activated", 'true' );
+ update_option( "fs_wc_migration_activated", 'true' );
}
register_activation_hook( __FILE__, 'fs_migration_plugin_activation' );
diff --git a/includes/class-fs-entity-mapper.php b/includes/class-fs-entity-mapper.php
index cb7ec04..a9951cb 100644
--- a/includes/class-fs-entity-mapper.php
+++ b/includes/class-fs-entity-mapper.php
@@ -28,7 +28,7 @@ class FS_Entity_Mapper {
private $_table_name;
/**
- * @var string E.g. EDD or WOO
+ * @var string E.g. WC or WOO
*/
private $_namespace;
diff --git a/includes/class-fs-logger.php b/includes/class-fs-logger.php
index 7995278..3e1003e 100644
--- a/includes/class-fs-logger.php
+++ b/includes/class-fs-logger.php
@@ -1,6 +1,6 @@
api_call(
"/users/{$customer_id}/plans/{$this->get_plan_id()}/pricing/{$this->get_pricing_id()}.json",
'post',
diff --git a/includes/migration/class-fs-migration-endpoint-abstract.php b/includes/migration/class-fs-migration-endpoint-abstract.php
index 067d949..0ea313e 100644
--- a/includes/migration/class-fs-migration-endpoint-abstract.php
+++ b/includes/migration/class-fs-migration-endpoint-abstract.php
@@ -66,7 +66,7 @@ protected function init( $namespace ) {
add_action( 'init', array( $this, 'maybe_process_api_request' ) );
}
- // Reduce query load for EDD API calls
+ // Reduce query load for API calls.
add_action( 'after_setup_theme', array( $this, 'reduce_query_load' ) );
add_action( 'admin_menu', array( &$this, '_add_submenu' ), 99999999 );
@@ -173,7 +173,7 @@ protected function link_entity( FS_Entity $entity, $local_entity_id ) {
function get_remote_paid_plan_id( $local_module_id ) {
return $this->get_remote_id(
FS_Plan::get_type(),
- $local_module_id . ':' . ( edd_has_variable_prices( $local_module_id ) ? '1' : '0' )
+ $this->get_local_paid_plan_id( $local_module_id )
);
}
@@ -301,7 +301,7 @@ function _notices() {
function _add_submenu() {
// Add Freemius submenu item.
$hook = add_submenu_page(
- 'edit.php?post_type=download',
+ 'woocommerce',
'Freemius',
'Freemius',
'manage_options',
@@ -358,7 +358,7 @@ function _save_settings() {
}
/**
- * Get all EDD downloads mapped to FS objects for the settings page.
+ * Get all products mapped to FS objects for the settings page.
*
* @author Vova Feldman
* @since 1.0.0
@@ -797,7 +797,7 @@ public function _sync_module_to_freemius_callback() {
$local_module = $this->get_local_module_by_id( $local_module_id );
if ( false === $local_module ) {
- // Post not exist or not an EDD download.
+ // Post not exist.
$this->shoot_json_failure( "There's no local module with the specified ID ({$local_module_id})." );
}
@@ -905,6 +905,18 @@ abstract protected function get_local_module_migration_manager( $local_module, F
*/
abstract protected function get_local_module_by_id( $local_module_id );
+ /**
+ * Should return the local plan ID.
+ *
+ * @author Vova Feldman
+ * @since 1.0.0
+ *
+ * @param string $local_module_id
+ *
+ * @return string
+ */
+ abstract protected function get_local_paid_plan_id( $local_module_id );
+
/**
* Should return an array of all local modules.
*
diff --git a/includes/migration/class-fs-module-migration-abstract.php b/includes/migration/class-fs-module-migration-abstract.php
index 19cb6be..52415d4 100644
--- a/includes/migration/class-fs-module-migration-abstract.php
+++ b/includes/migration/class-fs-module-migration-abstract.php
@@ -316,7 +316,7 @@ abstract protected function get_local_paid_plan_pricing_count();
* Get local paid plan pricing unique IDs.
*
* This case is relevant when there are different pricing objects for the
- * same feature-set but different license activations limit like in EDD.
+ * same feature-set but different license activations limit like in EDD or WC.
*
* @author Vova Feldman (@svovaf)
* @since 1.0.0
@@ -1017,4 +1017,4 @@ private function delete_plan( $plan_id ) {
}
#endregion
- }
\ No newline at end of file
+ }
diff --git a/includes/migration/edd/class-fs-edd-migration-endpoint.php b/includes/migration/edd/class-fs-edd-migration-endpoint.php
deleted file mode 100644
index 6428660..0000000
--- a/includes/migration/edd/class-fs-edd-migration-endpoint.php
+++ /dev/null
@@ -1,343 +0,0 @@
-init( WP_FS__NAMESPACE_EDD );
-
- if ( false && ! defined( 'DOING_AJAX' ) ) {
- $this->test_full_migration();
- }
- }
-
- #--------------------------------------------------------------------------------
- #region Testing
- #--------------------------------------------------------------------------------
-
- /**
- * Migrate license by ID.
- *
- * Note: This method is only for testing reasons.
- *
- * @author Vova Feldman (@svovaf)
- * @since 1.0.0
- *
- * @param int $license_id
- *
- * @throws Exception
- */
- function migrate_license_by_id( $license_id ) {
- require_once WP_FSM__DIR_MIGRATION . '/class-fs-migration-abstract.php';
- require_once WP_FSM__DIR_MIGRATION . '/edd/class-fs-edd-migration.php';
-
- $migration = FS_EDD_Migration::instance( $license_id );
- $migration->set_api( $this->get_api() );
- $migration->do_migrate_license();
- }
-
- /**
- * Test full install's license migration.
- *
- * @author Vova Feldman (@svovaf)
- * @since 1.0.0
- */
- private function test_full_migration() {
- $url = 'http://test9.freemius.com';
- $download_id = 25;
- $license_key = '74062bc8b9cc256823f8f08d0f8feedf';
-
- $params = array(
- 'license_key' => $license_key,
- 'module_id' => $download_id,
- 'url' => $url,
- 'site_url' => $url,
- 'plugin_version' => '1.2.1',
- 'site_uid' => $this->get_anonymous_id( $url ),
- 'site_name' => 'Freemius Test',
- 'platform_version' => get_bloginfo( 'version' ),
- 'php_version' => phpversion(),
- 'language' => get_bloginfo( 'language' ),
- 'charset' => get_bloginfo( 'charset' ),
- 'is_premium' => true,
- 'is_active' => true,
- 'is_uninstalled' => false,
- );
-
- $this->maybe_process_api_request( $params );
- }
-
- #endregion
-
- #--------------------------------------------------------------------------------
- #region Local Data Getters
- #--------------------------------------------------------------------------------
-
- /**
- * Map EDD download into FS object.
- *
- * @author Vova Feldman (@svovaf)
- * @since 1.0.0
- *
- * @param EDD_Download $local_module
- *
- * @return FS_Plugin
- */
- protected function local_to_remote_module( $local_module ) {
- $module = new FS_Plugin();
- $module->id = $local_module->get_ID();
- $module->slug = $local_module->post_name;
- $module->title = $local_module->get_name();
-
- return $module;
- }
-
- /**
- * Get all EDD downloads.
- *
- * @author Vova Feldman
- * @since 1.0.0
- *
- * @return array
- */
- protected function get_all_local_modules() {
- /**
- * @var WP_Post[] $downloads
- */
- $downloads = get_posts( array(
- 'post_type' => 'download',
- 'posts_per_page' => - 1,
- ) );
-
- for ( $i = 0, $len = count( $downloads ); $i < $len; $i ++ ) {
- $downloads[ $i ] = new EDD_Download( $downloads[ $i ]->ID );
- }
-
- return $downloads;
- }
-
- /**
- * Load EDD download by ID.
- *
- * @author Vova Feldman
- * @since 1.0.0
- *
- * @param string $local_module_id
- *
- * @return false|\EDD_Download
- */
- protected function get_local_module_by_id( $local_module_id ) {
- $download_post = WP_Post::get_instance( $local_module_id );
-
- return ( empty( $download_post ) || 'download' !== $download_post->post_type ) ?
- false :
- new EDD_Download( $local_module_id );
- }
-
- /**
- * EDD Download slug (post_name).
- *
- * @author Vova Feldman
- * @since 1.0.0
- *
- * @param mixed $local_module
- *
- * @return string
- */
- protected function get_local_module_slug( $local_module ) {
- return $local_module->post_name;
- }
-
- /**
- * Return the instance of the EDD download migration manager.
- *
- * @author Vova Feldman
- * @since 1.0.0
- *
- * @param mixed $local_module
- * @param FS_Plugin $module
- *
- * @return \FS_EDD_Download_Migration
- */
- protected function get_local_module_migration_manager( $local_module, FS_Plugin $module = null ) {
- require_once WP_FSM__DIR_MIGRATION . '/edd/class-fs-edd-download-migration.php';
-
- if ( is_null( $module ) ) {
- $module = $this->get_module_by_slug( $this->get_local_module_slug( $local_module ) );
- }
-
- return new FS_EDD_Download_Migration(
- $this->get_developer(),
- $module,
- $local_module
- );
- }
-
- #endregion
-
- /**
- * Migrate install's license and return FS account's data (user + install).
- *
- * @author Vova Feldman
- * @since 1.0.0
- *
- * @return array
- *
- * @throws FS_Endpoint_Exception
- */
- protected function migrate_install_license() {
- require_once WP_FSM__DIR_MIGRATION . '/class-fs-migration-abstract.php';
- require_once WP_FSM__DIR_MIGRATION . '/edd/class-fs-edd-migration.php';
-
- $license_id = edd_software_licensing()->get_license_by_key( $this->get_param( 'license_key' ) );
-
- $migration = FS_EDD_Migration::instance( $license_id );
- $migration->set_api( $this->get_api() );
-
- // Migrate customer, purchase/subscription, billing and license.
- $customer = $migration->do_migrate_license();
-
- // Migrate plugin installation.
- return $migration->do_migrate_install( $this->_request_data, $customer );
- }
-
- #--------------------------------------------------------------------------------
- #region API Request Params Validation
- #--------------------------------------------------------------------------------
-
- /**
- * Validate EDD download license parameters.
- *
- * @author Vova Feldman
- * @since 1.0.0
- *
- * @throws FS_Endpoint_Exception
- */
- protected function validate_params() {
- // Require download ID.
- $this->require_unsigned_int( 'module_id' );
-
- $download_id = $this->get_param( 'module_id' );
- $license_key = $this->get_param( 'license_key' );
- $url = $this->get_param( 'url' );
-
- // Before checking license with EDD, make sure module is synced.
- if (false === $this->get_remote_module_id( $download_id )){
- throw new FS_Endpoint_Exception( "Invalid download ID ({$download_id}).", 'invalid_download_id', 400 );
- }
-
- // Get EDD license state.
- $edd_license_state = edd_software_licensing()->check_license( array(
- 'item_id' => $download_id,
- 'item_name' => '',
- 'key' => $license_key,
- 'url' => $url,
- ) );
-
- switch ( $edd_license_state ) {
- case 'invalid':
- // Invalid license key.
- throw new FS_Endpoint_Exception( "Invalid license key ({$license_key}).", 'invalid_license_key',
- 400 );
- case 'invalid_item_id':
- // Invalid download ID.
- throw new FS_Endpoint_Exception( "Invalid download ID ({$download_id}).", 'invalid_download_id',
- 400 );
- /**
- * Migrate expired license since all EDD licenses are not blocking.
- */
- case 'expired':
- /**
- * License not yet activated.
- *
- * This use-case should not happen since if the client triggered a migration
- * request with a valid license key, it means that the license was activated
- * at least once. Hence, 'inactive' isn't possible.
- */
- case 'inactive':
- /**
- * License was disabled, therefore, ...
- *
- * @todo what to do in that case?
- */
- case 'disabled':
- /**
- * Migrate license & site.
- *
- * Based on the EDD SL logic this result is trigger when it's a production
- * site (not localhost), and the site license wasn't activated.
- *
- * It can happen for example when the user trying to activate a license
- * that is already fully utilized.
- *
- * @todo what to do in that case?
- */
- case 'site_inactive':
- /**
- * Migrate license & site.
- *
- * License is valid and activated for the context site.
- */
- case 'valid':
- break;
- case 'item_name_mismatch':
- /**
- * This use case should never happen since we check the license state
- * based on the EDD download ID, not the name.
- */
- break;
- default:
- // Unexpected license state. This case should never happen.
- throw new FS_Endpoint_Exception( 'Unexpected EDD download license state.' );
- break;
- }
- }
-
- #endregion
- }
-
- /**
- * The main function responsible for returning the FS_EDD_Migration_Endpoint
- * instance.
- *
- * Example:
- *
- * @author Vova Feldman
- * @since 1.0.0
- *
- * @return FS_EDD_Migration_Endpoint The one true Easy_Digital_Downloads Instance
- */
- function fs_edd_migration_manager() {
- return FS_EDD_Migration_Endpoint::instance();
- }
-
- // Get Freemius EDD Migration running.
- fs_edd_migration_manager();
\ No newline at end of file
diff --git a/includes/migration/wc/class-fs-wc-download-migration.php b/includes/migration/wc/class-fs-wc-download-migration.php
new file mode 100644
index 0000000..de6f293
--- /dev/null
+++ b/includes/migration/wc/class-fs-wc-download-migration.php
@@ -0,0 +1,342 @@
+>
+ */
+ private $_variations = array();
+
+ /**
+ * @var int
+ */
+ private $_free_price_id;
+
+ /**
+ * @var bool
+ */
+ private $_has_paid_plan = false;
+
+ /**
+ * @var array
+ */
+ private $_plan_pricing = array();
+
+ #--------------------------------------------------------------------------------
+ #region Init
+ #--------------------------------------------------------------------------------
+
+ function __construct( FS_Developer $developer, $module, WC_Product $product ) {
+ $this->_product = $product;
+
+ $this->init( WP_FS__NAMESPACE_WC, $developer, $module );
+
+ if ( $product->is_type('variable') ) {
+ $this->_variations = $this->_product->get_available_variations();
+ }
+
+ $this->process_local_pricing();
+ }
+
+ #endregion
+
+ #--------------------------------------------------------------------------------
+ #region Helper Methods
+ #--------------------------------------------------------------------------------
+
+ /**
+ * Get billing cycle out of the variable price.
+ *
+ * @author Vova Feldman (@svovaf)
+ * @since 1.0.0
+ *
+ * @todo Allow user to change this somehow
+ *
+ * @return string
+ */
+ private function get_billing_cycle( $id ) {
+ return 'annual';
+ }
+
+ /**
+ * @author Vova Feldman (@svovaf)
+ * @since 1.0.0
+ *
+ * @param number $id
+ *
+ * @return string
+ */
+ private function get_wc_unique_price_id( $id ) {
+ return $this->_product->id . ':' . $id;
+ }
+
+ /**
+ * Aggregate WC prices based on license limits.
+ *
+ * @author Vova Feldman (@svovaf)
+ * @since 1.0.0
+ */
+ private function process_local_pricing() {
+ $plan_pricing = array();
+
+ foreach ( $this->_variations as &$variation ) {
+ $variation['_id'] = $id = $variation['variation_id'];
+
+ $licenses = (int) get_post_meta( $id, '_api_activations', true );
+
+
+ // Check if free plan.
+ $amount = floatval( $variation['display_regular_price'] );
+ if ( .0 >= $amount ) {
+ $this->_free_price_id = $this->get_wc_unique_price_id( $id );
+ continue;
+ }
+
+ if ( ! isset( $plan_pricing[ $licenses ] ) ) {
+ $plan_pricing[ $licenses ] = array();
+ }
+
+ // Paid plan.
+ $plan_pricing[ $licenses ][] = $variation;
+
+ $this->_has_paid_plan = true;
+ }
+
+ foreach ( $plan_pricing as $licenses => $variations ) {
+ $pricing = array(
+ 'wc_prices_ids' => array()
+ );
+
+ $pricing['licenses'] = ( $licenses > 0 ) ? $licenses : null;
+
+ foreach ( $variations as $variation ) {
+ $amount = floatval( $variation['display_regular_price'] );
+
+ $billing_cycle = $this->get_billing_cycle( $variation['_id'] );
+ $pricing["{$billing_cycle}_price"] = $amount;
+
+ // We need to store WC price IDs list to link them with the pricing.
+ $pricing['wc_prices_ids'][] = $this->get_wc_unique_price_id( $variation['_id'] );
+ }
+
+ $this->_plan_pricing[] = $pricing;
+ }
+ }
+
+ #endregion
+
+ #--------------------------------------------------------------------------------
+ #region WC Required Data Getters
+ #--------------------------------------------------------------------------------
+
+ /**
+ * Get local module ID.
+ *
+ * @author Vova Feldman (@svovaf)
+ * @since 1.0.0
+ *
+ * @return bool
+ */
+ protected function get_local_module_id() {
+ return $this->_product->id;
+ }
+
+ /**
+ * Check if download has a free plan.
+ *
+ * @author Vova Feldman (@svovaf)
+ * @since 1.0.0
+ *
+ * @return bool
+ */
+ protected function local_has_free_plan() {
+ return isset( $this->_free_price_id );
+ }
+
+ /**
+ * Get free price ID as the plan ID since WC doesn't have a concept of plans.
+ *
+ * @author Vova Feldman (@svovaf)
+ * @since 1.0.0
+ *
+ * @return bool
+ */
+ protected function get_local_free_plan_id() {
+ return $this->_product->id . ':' . $this->_free_price_id . 'free';
+ }
+
+ /**
+ * Check download has any price that is not free.
+ *
+ * @author Vova Feldman (@svovaf)
+ * @since 1.0.0
+ *
+ * @return bool
+ */
+ protected function local_has_paid_plan() {
+ return $this->_has_paid_plan;
+ }
+
+ /**
+ * Return all the prices IDs that are paid and belong to the
+ * same plan (identical feature-set).
+ *
+ * @author Vova Feldman (@svovaf)
+ * @since 1.0.0
+ *
+ * @param int $index
+ *
+ * @return string[]
+ */
+ protected function get_local_paid_plan_pricing_ids( $index ) {
+ return $this->_plan_pricing[ $index ]['wc_prices_ids'];
+ }
+
+ /**
+ * Get paid plan associated pricing objects count.
+ *
+ * @author Vova Feldman (@svovaf)
+ * @since 1.0.0
+ *
+ * @return bool
+ */
+ protected function get_local_paid_plan_pricing_count() {
+ return count( $this->_plan_pricing );
+ }
+
+ /**
+ * @author Vova Feldman (@svovaf)
+ * @since 1.0.0
+ *
+ * @param int|null $licenses
+ *
+ * @return int|false
+ */
+ protected function get_local_paid_plan_pricing_index_by_licenses( $licenses ) {
+ $index = 0;
+
+ foreach ( $this->_plan_pricing as $pricing ) {
+ if ( $licenses === $pricing['licenses'] ) {
+ return $index;
+ }
+
+ $index ++;
+ }
+
+ return false;
+ }
+
+ /**
+ * @author Vova Feldman (@svovaf)
+ * @since 1.0.0
+ *
+ * @param int $index
+ *
+ * @return int|null
+ */
+ protected function get_local_paid_plan_pricing_licenses( $index ) {
+ return $this->_plan_pricing[ $index ]['licenses'];
+ }
+
+ #endregion
+
+ #--------------------------------------------------------------------------------
+ #region Data Mapping for API
+ #--------------------------------------------------------------------------------
+
+ /**
+ * Generate module details from local data for API.
+ *
+ * @author Vova Feldman
+ * @since 1.0.0
+ *
+ * @return array
+ */
+ protected function get_module_for_api() {
+ return array(
+ 'slug' => $this->_product->post->post_name,
+ 'title' => $this->_product->get_title(),
+ 'type' => 'plugin',
+ 'business_model' => $this->get_local_business_model(),
+ 'created_at' => $this->_product->post->post_date_gmt,
+ );
+ }
+
+ /**
+ * Generate free plan details from local data for API.
+ *
+ * @author Vova Feldman
+ * @since 1.0.0
+ *
+ * @return array
+ */
+ protected function get_free_plan_for_api() {
+ return array(
+ 'name' => 'free',
+ 'title' => 'Free',
+ );
+ }
+
+ /**
+ * Generate paid plan details from local data for API.
+ *
+ * @author Vova Feldman
+ * @since 1.0.0
+ *
+ * @return array
+ */
+ protected function get_paid_plan_for_api() {
+ return array(
+ 'name' => 'pro',
+ 'title' => 'Pro',
+ // By default create non-blocking plan.
+ 'is_block_features' => false,
+ 'is_https_support' => true,
+ // By default allow localhost activations.
+ 'is_free_localhost' => true,
+ // Set paid plan as featured.
+ 'is_featured' => true,
+ );
+ }
+
+ /**
+ * Generate paid plan pricing details from local data for API.
+ *
+ * @author Vova Feldman
+ * @since 1.0.0
+ *
+ * @param int $index
+ *
+ * @return array
+ */
+ protected function get_paid_plan_pricing_for_api( $index ) {
+ // Clone.
+ $pricing = $this->_plan_pricing[ $index ];
+
+ unset( $pricing['wc_prices_ids'] );
+
+ return $pricing;
+ }
+
+ #endregion
+ }
\ No newline at end of file
diff --git a/includes/migration/wc/class-fs-wc-migration-endpoint.php b/includes/migration/wc/class-fs-wc-migration-endpoint.php
new file mode 100644
index 0000000..9868672
--- /dev/null
+++ b/includes/migration/wc/class-fs-wc-migration-endpoint.php
@@ -0,0 +1,343 @@
+_order;
+ break;
+ default:
+ return $this->get_param( $name );
+ }
+
+ return null;
+ }
+
+ public static function instance() {
+ if ( ! isset( self::$_instance ) ) {
+ self::$_instance = new FS_WC_Migration_Endpoint();
+ }
+
+ return self::$_instance;
+ }
+
+ private function __construct() {
+
+ $this->init( WP_FS__NAMESPACE_WC );
+
+ add_action( 'init', array( $this, 'maybe_test_full_migration' ) );
+ }
+
+ #--------------------------------------------------------------------------------
+ #region Testing
+ #--------------------------------------------------------------------------------
+
+ /**
+ * Migrate license by ID.
+ *
+ * Note: This method is only for testing reasons.
+ *
+ * @author Vova Feldman (@svovaf)
+ * @since 1.0.0
+ *
+ * @param int $license_id
+ *
+ * @throws Exception
+ */
+ function migrate_license_by_id( $license_id ) {
+ $namespace = strtolower($this->_namespace);
+
+ require_once WP_FSM__DIR_MIGRATION . '/class-fs-migration-abstract.php';
+ require_once WP_FSM__DIR_MIGRATION . "/{$namespace}/class-fs-{$namespace}-migration.php";
+
+ $migration = FS_WC_Migration::instance( $license_id );
+ $migration->set_api( $this->get_api() );
+ $migration->do_migrate_license();
+ }
+
+ /**
+ * Test full install's license migration.
+ *
+ * @author Vova Feldman (@svovaf)
+ * @since 1.0.0
+ */
+ public function maybe_test_full_migration() {
+ if ( ! isset( $_GET['sfpfs-mig-test'] ) ) return;
+
+ require_once WP_FSM__DIR_INCLUDES . '/class-fs-endpoint-exception.php';
+
+ $url = 'http://wp/sfpfs/usr';
+ $license_key = 'wc_order_5645a84f75f0f_am_kyidNs5CzIlu';
+
+ $params = array(
+ 'license_key' => $license_key,
+ 'site_url' => $url,
+ 'url' => $url,
+ 'plugin_version' => '2.5.0',
+ 'is_premium' => true,
+ 'site_uid' => '19ec32f60ec07ef9fae025ce5ac6bb86', // FS site uid
+ 'site_name' => 'GetFrappe',
+ 'wcam_site_id' => 'rAnDoM12',
+ 'language' => 'en-US',
+ 'charset' => 'UTF-8',
+ 'platform_version' => '4.6.1',
+ 'php_version' => '7.0.0',
+ 'module_title' => 'Storefront Pro',
+ 'is_active' => true,
+ );
+
+ $this->maybe_process_api_request( $params );
+ }
+
+ #endregion
+
+ #--------------------------------------------------------------------------------
+ #region Local Data Getters
+ #--------------------------------------------------------------------------------
+
+ /**
+ * Return the WC plan ID.
+ *
+ * @author Vova Feldman
+ * @since 1.0.0
+ *
+ * @param string $product_id
+ *
+ * @return string
+ */
+ protected function get_local_paid_plan_id( $product_id ) {
+ $product = wc_get_product( $product_id );
+ return $product->get_parent() . ':' . $product_id;
+ }
+
+ /**
+ * Map WC download into FS object.
+ *
+ * @author Vova Feldman (@svovaf)
+ * @since 1.0.0
+ *
+ * @param WC_Product $local_module
+ *
+ * @return FS_Plugin
+ */
+ protected function local_to_remote_module( $local_module ) {
+ $module = new FS_Plugin();
+ $module->id = $local_module->id;
+ $module->slug = $local_module->post_name;
+ $module->title = $local_module->get_title();
+
+ return $module;
+ }
+
+ /**
+ * Get all WC downloads.
+ *
+ * @author Vova Feldman
+ * @since 1.0.0
+ *
+ * @return array
+ */
+ protected function get_all_local_modules() {
+ /**
+ * @var WP_Post[] $downloads
+ */
+ $downloads = get_posts( array(
+ 'post_type' => 'product',
+ 'posts_per_page' => - 1,
+ ) );
+
+ for ( $i = 0, $len = count( $downloads ); $i < $len; $i ++ ) {
+ $downloads[ $i ] = wc_get_product( $downloads[ $i ]->ID );
+ }
+
+ return $downloads;
+ }
+
+ /**
+ * Load WC download by ID.
+ *
+ * @author Vova Feldman
+ * @since 1.0.0
+ *
+ * @param string $local_module_id
+ *
+ * @return false|WC_Product
+ */
+ protected function get_local_module_by_id( $local_module_id ) {
+ return ( 'product' !== get_post_type( $local_module_id ) ) ? false :
+ wc_get_product( $local_module_id );
+ }
+
+ /**
+ * WC Download slug (post_name).
+ *
+ * @author Vova Feldman
+ * @since 1.0.0
+ *
+ * @param mixed $local_module
+ *
+ * @return string
+ */
+ protected function get_local_module_slug( $local_module ) {
+ return $local_module->post_name;
+ }
+
+ /**
+ * Return the instance of the WC download migration manager.
+ *
+ * @author Vova Feldman
+ * @since 1.0.0
+ *
+ * @param mixed $local_module
+ * @param FS_Plugin $module
+ *
+ * @return \FS_WC_Download_Migration
+ */
+ protected function get_local_module_migration_manager( $local_module, FS_Plugin $module = null ) {
+ require_once WP_FSM__DIR_MIGRATION . '/wc/class-fs-wc-download-migration.php';
+
+ if ( is_null( $module ) ) {
+ $module = $this->get_module_by_slug( $this->get_local_module_slug( $local_module ) );
+ }
+
+ return new FS_WC_Download_Migration(
+ $this->get_developer(),
+ $module,
+ $local_module
+ );
+ }
+
+ #endregion
+
+ /**
+ * Migrate install's license and return FS account's data (user + install).
+ *
+ * @author Vova Feldman
+ * @since 1.0.0
+ *
+ * @return array
+ *
+ * @throws FS_Endpoint_Exception
+ */
+ protected function migrate_install_license() {
+
+ require_once WP_FSM__DIR_MIGRATION . '/class-fs-migration-abstract.php';
+ require_once WP_FSM__DIR_MIGRATION . '/wc/class-fs-wc-migration.php';
+
+ $migration = FS_WC_Migration::instance( $this );
+
+ $migration->set_api( $this->get_api() );
+
+ // Migrate customer, purchase/subscription, billing and license.
+ $customer = $migration->do_migrate_license();
+
+ // Migrate plugin installation.
+ return $migration->do_migrate_install( $this->_request_data, $customer );
+ }
+
+ #--------------------------------------------------------------------------------
+ #region API Request Params Validation
+ #--------------------------------------------------------------------------------
+
+ /**
+ * Validate request parameters.
+ *
+ * @author Vova Feldman
+ * @since 1.0.0
+ *
+ * @throws FS_Endpoint_Exception
+ */
+ protected function validate_params() {
+ // Software title ( which may not be same as product title ) is plugin identifier in WCAM
+ $plugin_title = $this->get_param( 'module_title' );
+
+ if ( ! $this->get_param( 'email' ) ) {
+ $this->_request_data['email'] = $this->query_email_for_key();
+ }
+
+ // Get order
+ $order_data = WCAM()->helpers->get_order_info_by_email_with_order_key(
+ $this->get_param( 'email' ), $this->get_param( 'license_key' )
+ );
+
+ $order_data['product_id'] = empty( $order_data['variable_product_id'] ) ?
+ $order_data['parent_product_id'] : $order_data['variable_product_id'];
+
+ // Before checking license with WC, make sure module is synced.
+ if ( ! $order_data['product_id'] ){
+ throw new FS_Endpoint_Exception(
+ "You don't have permission to access plugin with identifier {$plugin_title}.", 'invalid_plugin_identifier',
+ 400
+ );
+ }
+
+ $this->_order = (object) $order_data;
+ }
+
+
+ private function query_email_for_key() {
+ global $wpdb;
+
+ $sql = "
+ SELECT user_email
+ FROM {$wpdb->prefix}woocommerce_downloadable_product_permissions
+ WHERE order_key = %s
+ ";
+
+ $args = explode( '_am_', $this->get_param('license_key') );
+
+ // Returns an Object
+ return $wpdb->get_var( $wpdb->prepare( $sql, $args ) );
+ }
+
+ #endregion
+ }
+
+ /**
+ * The main function responsible for returning the FS_WC_Migration_Endpoint
+ * instance.
+ *
+ * Example:
+ *
+ * @author Vova Feldman
+ * @since 1.0.0
+ *
+ * @return \FS_WC_Migration_Endpoint The one true FS_WC_Migration_Endpoint Instance
+ */
+ function fs_wc_migration_manager() {
+ return FS_WC_Migration_Endpoint::instance();
+ }
+
+ // Get Freemius WC Migration running.
+ fs_wc_migration_manager();
\ No newline at end of file
diff --git a/includes/migration/edd/class-fs-edd-migration.php b/includes/migration/wc/class-fs-wc-migration.php
similarity index 56%
rename from includes/migration/edd/class-fs-edd-migration.php
rename to includes/migration/wc/class-fs-wc-migration.php
index 33713ca..80d5c65 100644
--- a/includes/migration/edd/class-fs-edd-migration.php
+++ b/includes/migration/wc/class-fs-wc-migration.php
@@ -10,46 +10,30 @@
exit;
}
- class FS_EDD_Migration extends FS_Migration_Abstract {
-
- /**
- * @var EDD_Software_Licensing
- */
- protected static $_edd_sl;
+ class FS_WC_Migration extends FS_Migration_Abstract {
+ /** @var FS_WC_Migration_Endpoint Instance */
+ protected $ep;
protected $_is_subscription = false;
- #region EDD Entities
+ #region WC Entities
- /**
- * @var EDD_Download
- */
- protected $_edd_download;
+ /** @var WC_Product Current product instance */
+ protected $_product;
- /**
- * @var WP_Post
- */
+ /** @var WP_Post */
protected $_edd_license;
- /**
- * @var EDD_Customer
- */
- protected $_edd_customer;
+ /** @var null Not implemented */
+ protected $_wc_subscription;
- /**
- * @var EDD_Subscription
- */
- protected $_edd_subscription;
+ /** @var WC_Order Current order instance */
+ protected $_wc_order;
/**
- * @var EDD_Payment
- */
- protected $_edd_payment;
-
- /**
- * @var EDD_Payment[]
+ * @var WC_Payment[]
*/
protected $_edd_renewals = array();
@@ -64,26 +48,23 @@ class FS_EDD_Migration extends FS_Migration_Abstract {
#region Singleton
#--------------------------------------------------------------------------------
- private static $_instances = array();
+ /** @var FS_WC_Migration Instance */
+ private static $_instance;
/**
* @author Vova Feldman
* @since 1.0.0
*
- * @param int $license_id
+ * @param FS_WC_Migration_Endpoint $endpoint
*
- * @return FS_EDD_Migration
+ * @return FS_WC_Migration
*/
- public static function instance( $license_id ) {
- if ( ! isset( self::$_edd_sl ) ) {
- self::$_edd_sl = edd_software_licensing();
+ public static function instance( $endpoint ) {
+ if ( ! isset( self::$_instance ) ) {
+ self::$_instance = new FS_WC_Migration( $endpoint );
}
- if ( ! isset( self::$_instances[ $license_id ] ) ) {
- self::$_instances[ $license_id ] = new FS_EDD_Migration( $license_id );
- }
-
- return self::$_instances[ $license_id ];
+ return self::$_instance;
}
#endregion
@@ -92,59 +73,50 @@ public static function instance( $license_id ) {
#region Init
#--------------------------------------------------------------------------------
- private function __construct( $license_id ) {
- $this->init( WP_FS__NAMESPACE_EDD );
+ private function __construct( $endpoint ) {
+ $this->init( WP_FS__NAMESPACE_WC );
+
+ $this->ep = $endpoint;
- $this->load_edd_entities( $license_id );
+ $this->load_edd_entities();
}
/**
- * Pre-load all required EDD entities for complete migration process.
+ * Pre-load all required WC entities for complete migration process.
*
* @author Vova Feldman
* @since 1.0.0
- *
- * @param int $license_id
*/
- private function load_edd_entities( $license_id ) {
- $download_id = get_post_meta( $license_id, '_edd_sl_download_id', true );
- $initial_payment_id = get_post_meta( $license_id, '_edd_sl_payment_id', true );
- $customer_id = edd_get_payment_customer_id( $initial_payment_id );
+ private function load_edd_entities() {
+
+ $this->_product = wc_get_product( $this->ep->order->product_id );
+ $this->_wc_order = new WC_Order( $this->ep->order->order_id ); //@TODO Replace with WC equivalent for WC_Payment( $initial_payment_id );
- $this->_edd_license = get_post( $license_id );
- $this->_edd_download = new EDD_Download( $download_id );
- $this->_edd_customer = new EDD_Customer( $customer_id );
- $this->_edd_payment = new EDD_Payment( $initial_payment_id );
+ return; // Subscriptions not implemented
- $this->_edd_subscription = $this->get_edd_subscription(
+ $this->_wc_subscription = $this->get_wc_subscription(
$download_id,
$initial_payment_id
);
- if ( is_object( $this->_edd_subscription ) ) {
+ if ( is_object( $this->_wc_subscription ) ) {
/**
* Load renewals data.
*
* @var WP_Post[] $edd_renewal_posts
*/
- $edd_renewal_posts = $this->_edd_subscription->get_child_payments();
+ $edd_renewal_posts = $this->_wc_subscription->get_child_payments();
if ( is_array( $edd_renewal_posts ) && 0 < count( $edd_renewal_posts ) ) {
foreach ( $edd_renewal_posts as $edd_renewal_post ) {
- $this->_edd_renewals[] = new EDD_Payment( $edd_renewal_post->ID );
+ $this->_edd_renewals[] = new WC_Payment( $edd_renewal_post->ID );
}
}
}
}
- #endregion
-
- #--------------------------------------------------------------------------------
- #region Helper Methods
- #--------------------------------------------------------------------------------
-
/**
- * Get EDD subscription entity when license associated with a subscription.
+ * Get WC subscription entity when license associated with a subscription.
*
* @author Vova Feldman
* @since 1.0.0
@@ -152,22 +124,24 @@ private function load_edd_entities( $license_id ) {
* @param int $download_id
* @param int $parent_payment_id
*
- * @return \EDD_Subscription|false
+ * @return \WC_Subscription|false
*/
- private function get_edd_subscription( $download_id, $parent_payment_id ) {
- if ( ! class_exists( 'EDD_Recurring' ) ) {
- // EDD recurring payments add-on isn't installed.
+ private function get_wc_subscription( $download_id, $parent_payment_id ) {
+ throw new Exception( 'Not implemented' );
+
+ if ( ! class_exists( 'WC_Recurring' ) ) {
+ // WC recurring payments add-on isn't installed.
return false;
}
/**
* We need to make sure the singleton is initiated, otherwise,
- * EDD_Subscriptions_DB will not be found because the inclusion
+ * WC_Subscriptions_DB will not be found because the inclusion
* of the relevant file is executed in the instance init.
*/
- EDD_Recurring::instance();
+ WC_Recurring::instance();
- $subscriptions_db = new EDD_Subscriptions_DB();
+ $subscriptions_db = new WC_Subscriptions_DB();
$edd_subscriptions = $subscriptions_db->get_subscriptions( array(
'product_id' => $download_id,
@@ -181,6 +155,11 @@ private function get_edd_subscription( $download_id, $parent_payment_id ) {
#endregion
+ #--------------------------------------------------------------------------------
+ #region Local Data Getters
+ #--------------------------------------------------------------------------------
+
+
/**
* Init install migration data before
*
@@ -193,10 +172,6 @@ protected function set_local_install( $local_install ) {
$this->_edd_install_data = $local_install;
}
- #--------------------------------------------------------------------------------
- #region Local Data Getters
- #--------------------------------------------------------------------------------
-
/**
* Local module ID.
*
@@ -206,7 +181,7 @@ protected function set_local_install( $local_install ) {
* @return string
*/
protected function get_local_module_id() {
- return $this->_edd_download->ID;
+ return $this->ep->order->parent_product_id;
}
/**
@@ -218,13 +193,30 @@ protected function get_local_module_id() {
* @return string
*/
protected function get_local_license_id() {
- return $this->_edd_license->ID;
+
+ global $wpdb;
+
+ $sql = "
+ SELECT permission_id
+ FROM {$wpdb->prefix}woocommerce_downloadable_product_permissions
+ WHERE user_email = %s
+ AND order_key = %s
+ AND product_id = %s";
+
+ $args = array(
+ $this->ep->order->license_email,
+ $this->ep->order->order_key,
+ $this->ep->order->product_id,
+ );
+
+ // Returns an Object
+ return $wpdb->get_var( $wpdb->prepare( $sql, $args ) );
}
/**
* Local install ID.
*
- * There's no module install concept nor entity in EDD, therefore,
+ * There's no module install concept nor entity in WC, therefore,
* generate a unique ID based on the download ID and site canonized URL.
*
* @author Vova Feldman
@@ -237,12 +229,7 @@ protected function get_local_install_id() {
* Limit the ID to 32 chars since the entity mapping
* local_id column is limited to 32 chars.
*/
- return substr(
- $this->_edd_download->ID . '_' .
- md5( $this->get_edd_canonized_site_home_url() ),
- 0,
- 32
- );
+ return $this->ep->wcam_site_id;
}
/**
@@ -254,7 +241,7 @@ protected function get_local_install_id() {
* @return string
*/
protected function get_local_customer_id() {
- return $this->_edd_customer->id;
+ return $this->ep->order->user_id;
}
/**
@@ -266,13 +253,13 @@ protected function get_local_customer_id() {
* @return string
*/
protected function get_local_customer_email() {
- return $this->_edd_customer->email;
+ return $this->ep->order->license_email;
}
/**
* Local billing details ID.
*
- * EDD doesn't have a billing entity so associate it with the customer ID.
+ * WC doesn't have a billing entity so associate it with the customer ID.
*
* @author Vova Feldman
* @since 1.0.0
@@ -280,18 +267,18 @@ protected function get_local_customer_email() {
* @return string
*/
protected function get_local_billing_id() {
- return $this->_edd_customer->id;
+ return $this->ep->order->user_id;
}
/**
* Local pricing ID.
*
- * EDD doesn't have a unique pricing ID.
- * 1. When EDD SL is installed and the license is associated
+ * WC doesn't have a unique pricing ID.
+ * 1. When WC SL is installed and the license is associated
* with a variable price, use the download ID with the variable
* price ID ("{download->id}:{price->id}").
- * 2. When EDD SL is NOT installed, use "{download->id}:0" as the pricing ID.
- * 3. When EDD SL is installed but it's a legacy license that is NOT associated
+ * 2. When WC SL is NOT installed, use "{download->id}:0" as the pricing ID.
+ * 3. When WC SL is installed but it's a legacy license that is NOT associated
* with variable price, find the price ID based on the license activations limit,
* and use "{download->id}:{price->id}".
* If the license activation quota is different from all the quotas in the prices
@@ -304,58 +291,9 @@ protected function get_local_billing_id() {
* @return string
*/
protected function get_local_pricing_id() {
- $price_id = 0;
-
- if ( edd_has_variable_prices( $this->_edd_download->ID ) ) {
-
- $price_id = (int) self::$_edd_sl->get_price_id( $this->_edd_license->ID );
-
- if ( 0 === $price_id ) {
- /**
- * Couldn't find matching price ID which means it's a legacy license.
- *
- * Fetch the price ID that has the same license activations quota.
- */
- $edd_prices = $this->_edd_download->get_prices();
-
- $edd_license_activations_limit = self::$_edd_sl->get_license_limit( $this->_edd_download->ID,
- $this->_edd_license->ID );
-
- $price_found = false;
- foreach ( $edd_prices as $id => $edd_price ) {
- if ( $edd_license_activations_limit == $edd_price['license_limit'] ) {
- $price_id = $id;
- $price_found = true;
- break;
- }
- }
-
- if ( ! $price_found ) {
- /**
- * If license limit isn't matching any of the prices, use the first
- * price ID.
- */
- reset( $edd_prices );
- $price_id = key( $edd_prices );
- }
- }
- }
-
- return $this->_edd_download->ID . ':' . $price_id;
+ return $this->ep->order->parent_product_id . ':' . $this->ep->order->product_id;
}
- /**
- * Local plan ID.
- *
- * Since EDD doesn't have a concept of plans and since we locally
- * link all local pricing to the remote paid plan, use the local pricing ID
- * as the local plan ID.
- *
- * @author Vova Feldman
- * @since 1.0.0
- *
- * @return string
- */
protected function get_local_paid_plan_id() {
return $this->get_local_pricing_id();
}
@@ -363,7 +301,7 @@ protected function get_local_paid_plan_id() {
/**
* Local payment ID. When subscription return the initial payment ID.
*
- * Since EDD's initial payment is associated to a cart and can contain
+ * Since WC's initial payment is associated to a cart and can contain
* multiple products, set the unique per download ID as the download ID
* with the payment ID combination.
*
@@ -375,7 +313,7 @@ protected function get_local_paid_plan_id() {
protected function get_local_payment_id() {
// The initial payment can be associated to multiple downloads,
// therefore, we want to make it unique per module.
- return $this->_edd_download->ID . ':' . $this->_edd_payment->ID;
+ return 'wc_paid_' . $this->ep->order->product_id . '_' . $this->ep->order->order_id;
}
/**
@@ -384,10 +322,10 @@ protected function get_local_payment_id() {
* @author Vova Feldman
* @since 1.0.0
*
- * @return bool
+ * @return false
*/
protected function local_is_subscription() {
- return is_object( $this->_edd_subscription );
+ return false;
}
/**
@@ -396,10 +334,10 @@ protected function local_is_subscription() {
* @author Vova Feldman
* @since 1.0.0
*
- * @return string
+ * @return null No subscriptions
*/
protected function get_local_subscription_id() {
- return $this->_edd_subscription->id;
+ return null;
}
/**
@@ -412,9 +350,7 @@ protected function get_local_subscription_id() {
* @return int
*/
protected function get_local_renewals_count() {
- return is_array( $this->_edd_renewals ) ?
- count( $this->_edd_renewals ) :
- 0;
+ return 0;
}
/**
@@ -428,7 +364,7 @@ protected function get_local_renewals_count() {
* @return string
*/
protected function get_local_subscription_renewal_id( $index = 0 ) {
- return $this->_edd_renewals[ $index ]->ID;
+ return null;
}
#endregion
@@ -451,7 +387,7 @@ protected function get_local_subscription_renewal_id( $index = 0 ) {
* @return array
*/
private function get_customer_address_for_api() {
- $user_info = $this->_edd_payment->user_info;
+ $user_info = $this->_wc_order->get_address();
$address = array(
'line1' => '',
@@ -464,9 +400,9 @@ private function get_customer_address_for_api() {
if ( ! empty( $user_info['address'] ) ) {
$address = wp_parse_args( $user_info['address'], $address );
- } else if ( ! empty( $this->_edd_customer->user_id ) ) {
+ } else if ( ! empty( $this->ep->order->user_id ) ) {
// Enrich data with customer's address.
- $customer_address = get_user_meta( $this->_edd_customer->user_id, '_edd_user_address', true );
+ $customer_address = get_user_meta( $this->ep->order->user_id, '_edd_user_address', true );
$address = wp_parse_args( $customer_address, $address );
}
@@ -495,7 +431,7 @@ private function get_customer_address_for_api() {
}
/**
- * Generate payment gross and tax for API based on given EDD payment.
+ * Generate payment gross and tax for API based on given WC payment.
*
* When initial payment associated with a cart that have multiple products,
* find the gross and tax for the product that is associated with the context
@@ -504,43 +440,22 @@ private function get_customer_address_for_api() {
* @author Vova Feldman
* @since 1.0.0
*
- * @param EDD_Payment $edd_payment
+ * @param WC_Order $order
*
* @return array
*/
- private function get_payment_gross_and_tax_for_api( EDD_Payment $edd_payment ) {
- $gross_and_vat = array();
-
- if ( isset( $edd_payment->cart_details ) &&
- is_array( $edd_payment->cart_details ) &&
- 1 < count( $edd_payment->cart_details )
- ) {
- /**
- * Purchased multiple products in the same cart, find the gross & tax paid for the
- * product associated with the license.
- */
- $cart = $edd_payment->cart_details;
- $context_edd_download_name = $this->_edd_download->get_name();
- foreach ( $cart as $edd_download ) {
- if ( $context_edd_download_name === $edd_download['name'] ) {
- $gross_and_vat['gross'] = $edd_download['price'];
-
- if ( is_numeric( $edd_download['tax'] ) && $edd_download['tax'] > 0 ) {
- $gross_and_vat['vat'] = $edd_download['tax'];
- }
+ private function get_payment_gross_and_tax_for_api( WC_Order $order ) {
+ $order_item = $order->get_items();
- break;
- }
- }
- } else {
- /**
- * Purchased only one product, get the gross & tax directly from the total
- * payment.
- */
- $gross_and_vat['gross'] = $edd_payment->total;
+ $gross_and_vat = array(
+ 'gross' => 0,
+ 'vat' => 0,
+ );
- if ( is_numeric( $edd_payment->tax ) && $edd_payment->tax > 0 ) {
- $gross_and_vat['vat'] = $edd_payment->tax;
+ foreach( $order_item as $product ) {
+ if ( $product['product_id'] == $this->ep->order->product_id ) {
+ $gross_and_vat['gross'] = $product['line_total'];
+ $gross_and_vat['vat'] = $product['line_tax'];
}
}
@@ -554,14 +469,14 @@ private function get_payment_gross_and_tax_for_api( EDD_Payment $edd_payment ) {
* @author Vova Feldman
* @since 1.0.0
*
- * @return string|null
+ * @param WC_Order $order
+ *
+ * @return null|string
*/
- private function get_local_license_expiration() {
- $license_expiration = self::$_edd_sl->get_license_expiration( $this->_edd_license->ID );
+ private function get_local_license_expiration( $order = null ) {
+ if ( ! $order ) $order = $this->_wc_order;
- if ( 'lifetime' === $license_expiration ) {
- return null;
- }
+ $time = strtotime( $order->order_date );
$timezone = date_default_timezone_get();
@@ -570,7 +485,8 @@ private function get_local_license_expiration() {
date_default_timezone_set( 'UTC' );
}
- $formatted_license_expiration = date( WP_FSM__LOG_DATETIME_FORMAT, $license_expiration );
+ // Expire 1 year after purchase
+ $formatted_license_expiration = date( WP_FSM__LOG_DATETIME_FORMAT, $time + YEAR_IN_SECONDS );
if ( 'UTC' !== $timezone ) {
// Revert timezone.
@@ -580,77 +496,6 @@ private function get_local_license_expiration() {
return $formatted_license_expiration;
}
- /**
- * Try to get customer's IP address.
- *
- * - First try to get from the initial payment info.
- * - Then, from the renewals.
- * - Finally, check the EDD activations log and try to get it from there.
- *
- * If can't find it, return false.
- *
- * @author Vova Feldman
- * @since 1.0.0
- *
- * @return string|false
- */
- private function get_customer_ip() {
- // Try to get IP from initial payment.
- if ( ! empty( $this->_edd_payment->ip ) ) {
- return $this->_edd_payment->ip;
- }
-
- // Try to get IP from the subscription renewals.
- if ( $this->local_is_subscription() &&
- is_array( $this->_edd_renewals )
- ) {
- foreach ( $this->_edd_renewals as $edd_renewal ) {
- if ( ! empty( $edd_renewal->ip ) ) {
- return $edd_renewal->ip;
- }
- }
- }
-
- // Try to fetch IP from license activation log.
- $logs = edd_software_licensing()->get_license_logs( $this->_edd_license->ID );
- if ( is_array( $logs ) && 0 < count( $logs ) ) {
- $activation_log_post_name_prefix = 'log-license-activated-';
- $activation_log_post_name_prefix_length = strlen( $activation_log_post_name_prefix );
-
- foreach ( $logs as $log ) {
- if ( ! has_term( 'renewal_notice', 'edd_log_type', $log->ID ) ) {
- /**
- * @var WP_Post $log
- */
- if ( $activation_log_post_name_prefix === substr( $log->post_name, 0,
- $activation_log_post_name_prefix_length )
- ) {
- $activation_info = json_decode( get_post_field( 'post_content', $log->ID ) );
- if ( isset( $activation_info->REMOTE_ADDR ) &&
- ! empty( $activation_info->REMOTE_ADDR )
- ) {
- return $activation_info->REMOTE_ADDR;
- }
- }
- }
- }
- }
-
- return false;
- }
-
- /**
- * Check if sandbox purchase.
- *
- * @author Vova Feldman
- * @since 1.0.0
- *
- * @return bool
- */
- private function local_is_sandbox_purchase() {
- return ( 'live' !== $this->_edd_payment->mode );
- }
-
/**
* Get purchase gateway.
*
@@ -681,18 +526,6 @@ private function get_local_subscription_gateway() {
return $this->get_local_purchase_gateway();
}
- /**
- * Check if sandbox subscription.
- *
- * @author Vova Feldman
- * @since 1.0.0
- *
- * @return bool
- */
- private function is_sandbox_subscription() {
- return $this->local_is_sandbox_purchase();
- }
-
/**
* Get billing cycle in months.
*
@@ -702,7 +535,10 @@ private function is_sandbox_subscription() {
* @return int
*/
private function get_local_billing_cycle_in_months() {
- switch ( $this->_edd_subscription->period ) {
+ // @todo Adjust to work with WC Subscriptions plugin. For now, assume annual plans.
+ return 12;
+
+ switch ( $this->_wc_subscription->period ) {
case 'day':
case 'week':
// @todo The shortest supported billing period by Freemius is a Month.
@@ -719,37 +555,20 @@ private function get_local_billing_cycle_in_months() {
}
/**
- * Get EDD payment's processing date.
- *
- * If payment was never completed, return the payment entity creation datetime.
+ * Get WC payment's transaction ID. If empty, use "edd_payment_{payment_id}".
*
* @author Vova Feldman
* @since 1.0.0
*
- * @param EDD_Payment $edd_payment
+ * @param WC_Order $order
*
* @return string
*/
- private function get_payment_process_date( EDD_Payment $edd_payment ) {
- return ! empty( $edd_payment->completed_date ) ?
- $edd_payment->completed_date :
- $edd_payment->date;
- }
-
- /**
- * Get EDD payment's transaction ID. If empty, use "edd_payment_{payment_id}".
- *
- * @author Vova Feldman
- * @since 1.0.0
- *
- * @param EDD_Payment $edd_payment
- *
- * @return string
- */
- private function get_payment_transaction_id( EDD_Payment $edd_payment ) {
- return ! empty( $edd_payment->transaction_id ) ?
- $edd_payment->transaction_id :
- 'edd_payment_' . $edd_payment->ID;
+ private function get_payment_transaction_id( WC_Order $order = null ) {
+ if ( ! $order ) {
+ $order = $this->_wc_order;
+ }
+ return "wc_payment_{$order->id}";
}
/**
@@ -758,22 +577,25 @@ private function get_payment_transaction_id( EDD_Payment $edd_payment ) {
* @author Vova Feldman
* @since 1.0.0
*
- * @param EDD_Payment $edd_payment
+ * @param WC_Order $order
*
* @return array
*/
- private function get_payment_by_edd_for_api( EDD_Payment $edd_payment ) {
+ private function get_payment_by_edd_for_api( WC_Order $order = null ) {
+ if ( ! $order ) {
+ $order = $this->_wc_order;
+ }
$payment = array();
- $payment['processed_at'] = $this->get_payment_process_date( $edd_payment );
- $payment['payment_external_id'] = $this->get_payment_transaction_id( $edd_payment );
+ $payment['processed_at'] = $order->order_date;
+ $payment['payment_external_id'] = $this->get_payment_transaction_id( $order );
- $payment = array_merge( $payment, $this->get_payment_gross_and_tax_for_api( $edd_payment ) );
+ $payment = array_merge( $payment, $this->get_payment_gross_and_tax_for_api( $order ) );
return $payment;
}
/**
- * Generate site's URL based on how EDD stores the URLs in the
+ * Generate site's URL based on how WC stores the URLs in the
* license post meta ('_edd_sl_sites').
*
* @author Vova Feldman
@@ -801,45 +623,6 @@ private function get_edd_canonized_site_home_url( $url = '' ) {
return trailingslashit( self::$_edd_sl->clean_site_url( $url ) );
}
- /**
- * Try to find installation date based on EDD license activation log.
- *
- * @author Vova Feldman
- * @since 1.0.0
- *
- * @return false|string
- */
- private function get_local_install_datetime() {
- $logs = edd_software_licensing()->get_license_logs( $this->_edd_license->ID );
-
- if ( is_array( $logs ) && 0 < count( $logs ) ) {
- $activation_log_post_name_prefix = 'log-license-activated-';
- $activation_log_post_name_prefix_length = strlen( $activation_log_post_name_prefix );
- $canonized_url = trim( $this->get_edd_canonized_site_home_url(), '/' );
-
- foreach ( $logs as $log ) {
- if ( ! has_term( 'renewal_notice', 'edd_log_type', $log->ID ) ) {
- /**
- * @var WP_Post $log
- */
- if ( $activation_log_post_name_prefix === substr( $log->post_name, 0,
- $activation_log_post_name_prefix_length )
- ) {
- $activation_info = json_decode( get_post_field( 'post_content', $log->ID ) );
- if ( isset( $activation_info->HTTP_USER_AGENT ) ) {
- if ( false !== strpos( $activation_info->HTTP_USER_AGENT, $canonized_url ) ) {
- // Found matching URL activation.
- return $log->post_date_gmt;
- }
- }
- }
- }
- }
- }
-
- return false;
- }
-
/**
* Get license quota. If unlimited license, return NULL.
*
@@ -849,11 +632,7 @@ private function get_local_install_datetime() {
* @return int|null
*/
private function get_license_quota() {
- $quota = (int) self::$_edd_sl->get_license_limit(
- $this->_edd_download->ID,
- $this->_edd_license->ID
- );
-
+ $quota = (int) $this->ep->order->_api_activations;
return ( $quota > 0 ) ? $quota : null;
}
@@ -869,13 +648,13 @@ private function get_license_quota() {
*/
protected function get_customer_for_api() {
$customer = array();
- $customer['email'] = $this->_edd_customer->email;
- $customer['name'] = $this->_edd_customer->name;
+ $customer['email'] = $this->ep->order->license_email;
+ $customer['name'] = $this->_wc_order->billing_first_name . ' ' . $this->_wc_order->billing_last_name;
$customer['is_verified'] = true;
$customer['send_verification_email'] = false; // Do NOT send verification emails.
$customer['password'] = wp_generate_password( 8 ); // Generate random 8 char pass for FS.
- $ip = $this->get_customer_ip();
+ $ip = $this->_wc_order->customer_ip_address;
if ( ! empty( $ip ) ) {
$customer['ip'] = $ip;
}
@@ -892,13 +671,11 @@ protected function get_customer_for_api() {
* @return array
*/
protected function get_customer_billing_for_api() {
- $payment_meta = $this->_edd_payment->payment_meta;
- $user_info = $this->_edd_payment->user_info;
$billing = array();
- $billing['first'] = $user_info['first_name'];
- $billing['last'] = $user_info['last_name'];
- $billing['email'] = $payment_meta['email'];
+ $billing['first'] = $this->_wc_order->billing_first_name;
+ $billing['last'] = $this->_wc_order->billing_last_name;
+ $billing['email'] = $this->_wc_order->billing_email;
$billing = array_merge( $billing, $this->get_customer_address_for_api() );
@@ -930,7 +707,7 @@ protected function get_install_for_api( $license_id ) {
$install['programming_language_version'] = $this->_edd_install_data['php_version'];
$install['license_id'] = $license_id;
- $install_at = $this->get_local_install_datetime();
+ $install_at = $this->ep->order->_purchase_time;
if ( ! empty( $install_at ) ) {
$install['installed_at'] = $install_at;
@@ -956,17 +733,6 @@ protected function get_purchase_vat_for_api() {
$vat['country_code'] = $address['address_country_code'];
}
- if ( class_exists( '\lyquidity\edd_vat\Actions' ) ) {
- if ( ! empty( $this->_edd_customer->user_id ) ) {
- $vat_id = \lyquidity\edd_vat\Actions::instance()->get_vat_number( '',
- $this->_edd_customer->user_id );
-
- if ( ! empty( $vat_id ) ) {
- $vat['vat_id'] = $vat_id;
- }
- }
- }
-
return $vat;
}
@@ -981,12 +747,11 @@ protected function get_purchase_vat_for_api() {
protected function get_purchase_for_api() {
$purchase = array();
$purchase['billing_cycle'] = 0;
- $purchase['payment_method'] = $this->get_local_purchase_gateway();
- $purchase['customer_external_id'] = 'edd_customer_' . $this->_edd_customer->id;
- $purchase['license_key'] = self::$_edd_sl->get_license_key( $this->_edd_license->ID ); // Preserve the same keys.
+ $purchase['customer_external_id'] = 'wc_customer_' . $this->ep->order->user_id;
+ $purchase['license_key'] = substr( $this->ep->order->api_key, 6 );
$purchase['license_quota'] = $this->get_license_quota(); // Preserve license activations limit.
- $purchase['processed_at'] = $this->get_payment_process_date( $this->_edd_payment );
- $purchase['payment_external_id'] = $this->get_payment_transaction_id( $this->_edd_payment );
+ $purchase['processed_at'] = $this->_wc_order->order_date;
+ $purchase['payment_external_id'] = $this->get_payment_transaction_id();
// Set license expiration if not a lifetime license via a purchase.
$license_expiration = $this->get_local_license_expiration();
@@ -994,11 +759,13 @@ protected function get_purchase_for_api() {
$purchase['license_expires_at'] = $license_expiration;
}
- if ( $this->local_is_sandbox_purchase() ) {
- $purchase['is_sandbox'] = true;
+ if ( false !== strpos( strtolower( $this->_wc_order->payment_method ), 'paypal' ) ) {
+ $purchase['payment_method'] = 'paypal';
+ } else {
+ $purchase['payment_method'] = 'cc';
}
- $purchase = array_merge( $purchase, $this->get_payment_gross_and_tax_for_api( $this->_edd_payment ) );
+ $purchase = array_merge( $purchase, $this->get_payment_gross_and_tax_for_api( $this->_wc_order ) );
$purchase = array_merge( $purchase, $this->get_purchase_vat_for_api() );
@@ -1025,19 +792,21 @@ protected function get_onetime_payment_for_api() {
* @author Vova Feldman
* @since 1.0.0
*
- * @return array
- */
+ * @return null
+ egion Helper Methods */
protected function get_subscription_for_api() {
+ throw new Exception( 'Not implemented' );
+
$subscription = array();
$subscription['payment_method'] = $this->get_local_subscription_gateway();
$subscription['billing_cycle'] = $this->get_local_billing_cycle_in_months();
- $subscription['subscription_external_id'] = ! empty( $this->_edd_subscription->profile_id ) ?
- $this->_edd_subscription->profile_id :
- 'edd_subscription_' . $this->_edd_subscription->id;
+ $subscription['subscription_external_id'] = ! empty( $this->_wc_subscription->profile_id ) ?
+ $this->_wc_subscription->profile_id :
+ 'edd_subscription_' . $this->_wc_subscription->id;
$subscription['customer_external_id'] = 'edd_customer_' . $this->_edd_customer->id;
- $subscription['next_payment'] = $this->_edd_subscription->get_expiration();
- $subscription['processed_at'] = $this->_edd_subscription->created;
+ $subscription['next_payment'] = $this->_wc_subscription->get_expiration();
+ $subscription['processed_at'] = $this->_wc_subscription->created;
$subscription['license_key'] = self::$_edd_sl->get_license_key( $this->_edd_license->ID ); // Preserve the same keys.
$subscription['license_quota'] = $this->get_license_quota(); // Preserve license activations limit.
@@ -1049,12 +818,8 @@ protected function get_subscription_for_api() {
*/
$subscription['license_expires_at'] = $this->get_local_license_expiration();
- if ( $this->is_sandbox_subscription() ) {
- $subscription['is_sandbox'] = true;
- }
-
// @todo Enrich API to accept is_cancelled as an optional argument during migration.
- if ( 'cancelled' === $this->_edd_subscription->get_status() ) {
+ if ( 'cancelled' === $this->_wc_subscription->get_status() ) {
$subscription['is_cancelled'] = true;
}
@@ -1081,11 +846,11 @@ protected function get_initial_payment_for_api() {
* From some reason when the gateway is Stripe the initial payment
* transaction ID is stored as the transaction ID of the subscription.
*/
- $transaction_id = $this->_edd_subscription->get_transaction_id();
+ $transaction_id = $this->_wc_subscription->get_transaction_id();
}
if ( empty( $transaction_id ) ) {
- // Fallback to EDD payment ID.
+ // Fallback to WC payment ID.
$transaction_id = 'edd_payment_' . $this->_edd_payment->ID;
}
@@ -1106,6 +871,8 @@ protected function get_initial_payment_for_api() {
* @return array
*/
protected function get_subscription_renewal_for_api( $index = 0 ) {
+ throw new Exception( 'Not implemented' );
+
$renewal = $this->get_payment_by_edd_for_api( $this->_edd_renewals[ $index ] );
// Don't extend license on renewal.
diff --git a/readme.txt b/readme.txt
index db378ba..eeef931 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,4 +1,4 @@
-=== Freemius for Easy Digital Downloads Migration ===
+=== Freemius for WooCommerce API Manager Migration ===
Contributors: freemius
Tags: freemius, fs, easy digital downloads, edd, bridge, adapter, add-on, plugins
Requires at least: 3.9
@@ -7,7 +7,7 @@ Stable Tag: 1.0
License: GPLv2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
-Lazy migration of EDD licenses to Freemius.
+Lazy migration of WC licenses to Freemius.
== Description ==
diff --git a/samples/module-migration.php b/samples/module-migration.php
index 47ac782..ccfb762 100644
--- a/samples/module-migration.php
+++ b/samples/module-migration.php
@@ -1,11 +1,11 @@
15,
'sslverify' => false,
@@ -129,7 +129,7 @@ function do_my_edd2fs_license_migration(
* @author Vova Feldman (@svovaf)
* @since 1.0.0
*
- * @param int $edd_download_id The context EDD download ID (from your store).
+ * @param int $edd_download_id The context WC download ID (from your store).
*
* @return bool Is successfully spawned the migration request.
*/
@@ -191,9 +191,9 @@ function spawn_my_edd2fs_license_migration( $edd_download_id ) {
* @author Vova Feldman (@svovaf)
* @since 1.0.0
*
- * @param int $edd_download_id The context EDD download ID (from your store).
- * @param string $edd_license_key The current site's EDD license key.
- * @param string $edd_store_url Your EDD store URL.
+ * @param int $edd_download_id The context WC download ID (from your store).
+ * @param string $edd_license_key The current site's WC license key.
+ * @param string $edd_store_url Your WC store URL.
* @param bool $is_blocking Special argument for testing. When false, will initiate the migration in the same
* HTTP request.
*
@@ -266,7 +266,7 @@ function my_non_blocking_edd2fs_license_migration(
}
/**
- * Try to activate EDD license.
+ * Try to activate WC license.
*
* @author Vova Feldman (@svovaf)
* @since 1.0.0
@@ -278,14 +278,14 @@ function my_non_blocking_edd2fs_license_migration(
function my_edd_activate_license( $license_key ) {
// Call the custom API.
$response = wp_remote_post(
- MY__EDD_STORE_URL,
+ MY__WC_STORE_URL,
array(
'timeout' => 15,
'sslverify' => false,
'body' => array(
'edd_action' => 'activate_license',
'license' => $license_key,
- 'item_id' => MY__EDD_DOWNLOAD_ID,
+ 'item_id' => MY__WC_DOWNLOAD_ID,
'url' => home_url()
)
)
@@ -300,7 +300,7 @@ function my_edd_activate_license( $license_key ) {
$license_data = json_decode( wp_remote_retrieve_body( $response ) );
if ( 'valid' === $license_data->license ) {
- // Store EDD license key.
+ // Store WC license key.
update_option( 'edd_sample_license_key', $license_key );
} else {
return false;
@@ -311,7 +311,7 @@ function my_edd_activate_license( $license_key ) {
/**
* If installation failed due to license activation on Freemius try to
- * activate the license on EDD first, and if successful, migrate the license
+ * activate the license on WC first, and if successful, migrate the license
* with a blocking request.
*
* This method will only be triggered upon failed module installation.
@@ -346,11 +346,11 @@ function my_try_migrate_on_activation( $response, $args ) {
( is_string( $response->error ) && false !== strpos( strtolower( $response->error ), 'license' ) )
) {
if ( my_edd_activate_license( $license_key ) ) {
- // Successfully activated license on EDD, try to migrate to Freemius.
+ // Successfully activated license on WC, try to migrate to Freemius.
if ( do_my_edd2fs_license_migration(
- MY__EDD_DOWNLOAD_ID,
+ MY__WC_DOWNLOAD_ID,
$license_key,
- MY__EDD_STORE_URL,
+ MY__WC_STORE_URL,
true
) ) {
/**
@@ -442,7 +442,7 @@ function fs_add_transient( $transient, $value, $expiration = 0 ) {
#endregion
if ( ! defined( 'DOING_CRON' ) ) {
- // Pull EDD license key from storage.
+ // Pull WC license key from storage.
$license_key = trim( get_option( 'edd_sample_license_key' ) );
/**
@@ -461,9 +461,9 @@ function fs_add_transient( $transient, $value, $expiration = 0 ) {
if ( ! empty( $license_key ) ) {
if ( ! defined( 'DOING_AJAX' ) ) {
my_non_blocking_edd2fs_license_migration(
- MY__EDD_DOWNLOAD_ID,
+ MY__WC_DOWNLOAD_ID,
$license_key,
- MY__EDD_STORE_URL
+ MY__WC_STORE_URL
);
}
}
diff --git a/templates/admin-notice.php b/templates/admin-notice.php
index f7cc81e..64656dc 100644
--- a/templates/admin-notice.php
+++ b/templates/admin-notice.php
@@ -1,6 +1,6 @@
| @@ -218,6 +218,7 @@ class=""> alert(''); } else { alert(''); + console.log( result ); } // Recover button's label. diff --git a/tests/order.txt b/tests/order.txt new file mode 100644 index 0000000..df416c2 --- /dev/null +++ b/tests/order.txt @@ -0,0 +1,23 @@ +# Contents of order array +array( + [user_id] => 2 + [order_id] => 21 + [order_key] => wc_order_abcdefgh12345 + [license_email] => theguy@example.com + [_api_software_title_parent] => Storefront Pro + [_api_software_title_var] => + [software_title] => Storefront Pro + [parent_product_id] => 10 + [variable_product_id] => + [current_version] => 3.5.0 + [_api_activations] => + [_api_activations_parent] => + [_api_update_permission] => yes + [is_variable_product] => no + [license_type] => + [expires] => + [_purchase_time] => 2016-11-03 05:40:08 + [_api_was_activated] => + [api_key] => wc_order_abcdefgh12345_am_rstuvwxy6789 + [product_id] => 10 +) \ No newline at end of file |