Products: Map Non-Supported Product Types to Supported Types

Map non-supported WooCommerce Product Types to supported Product Types in QPilot.

Important: Always test customizations to your site on a staging environment before making changes to your live / production site.  If you are not experienced with testing changes on a staging site, here is a good article to review.

/**
* Adjustments to Map a Custom Product Type ( i.e. Bundle ) as Simple for Autoship Support
* Includes Mapping the Types for Validation, Upsert, Sync Health, and WC Rest API.
* Updated 2020-05-29 : Updated to work with the 2.0+ QPilot API
*/////////////////////////////////////////////////////////////////////////////////////*/

/**
 * Is Mapped Type
 * @param string $type The current product type
 * @return bool True if it's an override type else false
 */
function xx_is_mapped_type( $type ){
  return 'bundle' == $type;
}

/**
 * Retrieves the correct type for QPilot
 * @param string $type  The current product type in WC
 * @return string The new type
 */
function xx_get_mapped_type( $type ){
  $types = array(
    'bundle'  => 'simple',
    'simple'  => 'bundle',
  );
  return isset( $types[$type] ) ? $types[$type] : $type;
}

/**
 * Extends the Valid Sync Types for Autoship
 * @param array $types The valid product types ( simple, variable, variation )
 * @return array The adjusted types.
 */
function xx_extend_autoship_product_sync_types( $types ){
  $types[] = 'bundle';
  return $types;
}
add_filter('autoship_valid_product_types', 'xx_extend_autoship_product_sync_types', 10, 1 );

/**
 * Maps types to Autoship Supported during Upsert
 * @param array $product_data The Product Data being upserted
 * @return array The adjusted data.
 */
function xx_map_autoship_product_sync_types_on_upsert( $product_data ){

  if ( !xx_is_mapped_type( $product_data['metadata']['type'] ) )
  return $product_data;

  $product_data['metadata']['type'] = xx_get_mapped_type( $product_data['metadata']['type'] );
  return $product_data;

}
add_filter('autoship_product_upsert_data', 'xx_map_autoship_product_sync_types_on_upsert', 10, 1 );


/**
 * Adjusts the Type for the Product Screens
 *
 * @param array $totals The current summary data
 * @param stdClass $summary The QPilot Summary data
 * @param WC_Product $product The WC Poduct
 * @return array The adjusted data.
 */
function xx_adjust_product_summary_data_for_custom_type( $totals, $product, $ids, $summaries ){

  if ( !xx_is_mapped_type( $product->get_type() ) )
  return $totals;

  // Retrieve the legacy availability string.
  $availability = 'None';
  if ( $summaries[0]->addToScheduledOrder && $summaries[0]->processScheduledOrder ){
    $availability = 'AddToScheduledOrder,ProcessScheduledOrder';
  } else if ( $summaries[0]->addToScheduledOrder ){
    $availability = 'AddToScheduledOrder';
  } else if ( $summaries[0]->processScheduledOrder  ){
    $availability = 'ProcessScheduledOrder';
  }

  $totals = apply_filters( 'autoship_product_summary_data', array(
    'Id'                            => $summaries[0]->id,
    'ProductName'                   => $summaries[0]->productName,
    'AddToScheduledOrder'           => $summaries[0]->addToScheduledOrder !== false,
    'ProcessScheduledOrder'         => $summaries[0]->processScheduledOrder !== false,
    'Availability'                  => $availability,
    'ProductType'                   => xx_get_mapped_type ( $summaries[0]->productType ),
    'StockLevel'                    => $summaries[0]->availability,
    'TotalStock'                    => $summaries[0]->stock,
    'QuantityScheduled'             => $summaries[0]->totalQuantityScheduledActive +
                                       $summaries[0]->totalQuantityScheduledPaused +
                                       $summaries[0]->totalQuantityFailed +
                                       $summaries[0]->totalQuantityProcessing +
                                       $summaries[0]->totalQuantityQueued,
    'TotalQuantityScheduledActive'  => $summaries[0]->totalQuantityScheduledActive,
    'TotalQuantityScheduledPaused'  => $summaries[0]->totalQuantityScheduledPaused,
    'TotalQuantityFailed'           => $summaries[0]->totalQuantityFailed,
    'TotalQuantityProcessing'       => $summaries[0]->totalQuantityProcessing,
    'TotalQuantityQueued'           => $summaries[0]->totalQuantityQueued,
    'LifetimeValue'                 => $summaries[0]->lifetimeValue,
    'ShippingClass'                 => $summaries[0]->shippingClass,
    'Active'                        => $summaries[0]->active,
    'Valid'                         => $summaries[0]->valid,
    'ValidationErrorCode'           => $summaries[0]->validationErrorCode,
    'UpdatedUtc'                    => $summaries[0]->updatedUtc,
    'SyncError'                     => ''
  ), $summaries[0], $product );

  // Since we've already pulled the Active flag from QPilot get the flag from WooCommerce / Autoship
  $totals['AutoshipActive'] = ( 'yes' === autoship_sync_active_enabled( $product ) );

  // Run Sync Checks
  $totals['SyncError'] = apply_filters( 'autoship_product_summary_data_sync_error', $totals['SyncError'], $totals, $summaries[0], $product, $ids );

  return apply_filters( 'autoship_total_product_summary_data', $totals, $product, $summaries );

}
add_filter( 'autoship_total_variation_product_summary_data', 'xx_adjust_product_summary_data_for_custom_type', 10, 4 );

/**
 * Maps types to Autoship Supported during Upsert
 * @param array $product_data The Product Data being upserted
 * @return array The adjusted data.
 */
function xx_gather_total_custom_type_all_products_summary_data( $totals, $summary ){

  $product = wc_get_product( $totals['Id'] );

  if ( xx_is_mapped_type( $product->get_type() ) )
  $totals['ProductType'] = xx_get_mapped_type( $totals['ProductType'] );

  return $totals;

}
add_filter('autoship_all_products_summary_data_row', 'xx_gather_total_custom_type_all_products_summary_data', 10, 2 );


/**
 * Dynamically Maps the WC Product Type to a valid QPilot Type.
 *
 * @param WP_REST_Response $response The response object.
 * @param WC_Data          $object   Object data.
 * @param WP_REST_Request  $request  Request object.
 *
 * @return WP_REST_Response
 */
 function xx_woocommerce_rest_prepare_object_change_product_type( $response, $object, $request ) {

   $response->data['type'] = xx_get_mapped_type( $response->data['type'] );
   return $response;

 }
add_filter('woocommerce_rest_prepare_product_object', 'xx_woocommerce_rest_prepare_object_change_product_type', 99, 3 );

Example Result