get_type(), self::all(), true );
}
/**
* Point each type at the data store its parent class expects.
*
* WooCommerce resolves the store by type name, so an unregistered one silently falls
* back to the simple-product store - which has no concept of children. A variable
* subscription loaded that way reports no variations at all.
*
* @param array $stores
*/
public function map_data_stores( $stores ): array {
$stores[ 'product-' . self::SIMPLE ] = 'WC_Product_Data_Store_CPT';
$stores[ 'product-' . self::VARIABLE ] = 'WC_Product_Variable_Data_Store_CPT';
return (array) $stores;
}
/**
* WooCommerce stores the type as a term, so a new one has to exist before a product
* can be saved as it.
*/
public function register_terms(): void {
foreach ( self::all() as $type ) {
if ( ! get_term_by( 'slug', $type, 'product_type' ) ) {
wp_insert_term( $type, 'product_type' );
}
}
}
/**
* @param array $types
*/
public function add_to_selector( $types ): array {
$types[ self::SIMPLE ] = __( 'Subscription', 'submex' );
// Offered only when something can bill it - but never taken away from a product
// that is already one, or saving the product would silently change its type.
if ( self::variable_supported() || self::VARIABLE === self::editing_type() ) {
$types[ self::VARIABLE ] = __( 'Variable subscription', 'submex' );
}
return (array) $types;
}
/**
* Tell an admin editing a variable subscription that it is not billing.
*/
public function warn_unsupported_variable(): void {
if ( self::variable_supported() || self::VARIABLE !== self::editing_type() ) {
return;
}
echo '
' . esc_html__(
'This is a variable subscription, but Submex Pro is not active, so nothing gives its variations a billing schedule. A customer buying one is charged once and never again. Activate Submex Pro, or change the product type to Subscription.',
'submex'
) . '
';
}
/**
* The product type of the product open in the editor, if one is.
*/
private static function editing_type(): string {
$screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null;
if ( ! $screen || 'product' !== $screen->id ) {
return '';
}
global $product_object, $post;
$product = $product_object instanceof \WC_Product ? $product_object : null;
if ( ! $product && $post instanceof \WP_Post && 'product' === $post->post_type ) {
$product = wc_get_product( $post );
}
return $product instanceof \WC_Product ? $product->get_type() : '';
}
/**
* @param string $classname
* @param string $type
*/
public function map_class( $classname, $type ): string {
return match ( $type ) {
self::SIMPLE => Simple_Subscription::class,
self::VARIABLE => Variable_Subscription::class,
default => (string) $classname,
};
}
/**
* @param array $tabs
*/
public function show_standard_tabs( $tabs ): array {
$classes = array_map( static fn( string $type ): string => 'show_if_' . $type, self::all() );
foreach ( array( 'general', 'inventory', 'shipping', 'linked_product', 'attribute', 'advanced' ) as $tab ) {
if ( isset( $tabs[ $tab ]['class'] ) ) {
$tabs[ $tab ]['class'] = array_merge( (array) $tabs[ $tab ]['class'], $classes );
}
}
if ( isset( $tabs['variations']['class'] ) ) {
$tabs['variations']['class'][] = 'show_if_' . self::VARIABLE;
}
return (array) $tabs;
}
/**
* WooCommerce shows the price fields only for types it ships with, and the variations
* machinery only for its own variable type. Both are class-driven in the DOM, so the
* fix is to let our types answer to the same classes.
*/
public function show_standard_fields(): void {
$screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null;
if ( ! $screen || 'product' !== $screen->id || ! wp_script_is( 'wc-admin-product-meta-boxes', 'enqueued' ) ) {
return;
}
$template = <<<'JS'
jQuery( function ( $ ) {
var simple = %1$s, variable = %2$s;
$( '.pricing' ).addClass( 'show_if_' + simple );
$( '.show_if_simple' ).not( '.submex-product-options' ).addClass( 'show_if_' + simple );
$( '.show_if_variable' ).addClass( 'show_if_' + variable );
$( 'body' ).trigger( 'woocommerce-product-type-change', $( '#product-type' ).val() );
} );
JS;
wp_add_inline_script( 'wc-admin-product-meta-boxes', sprintf( $template, wp_json_encode( self::SIMPLE ), wp_json_encode( self::VARIABLE ) ) );
}
/**
* @param bool $supports
* @param string $feature
*/
public function supports( $supports, $feature, $product ): bool {
if ( 'ajax_add_to_cart' === $feature && self::is_subscription_type( $product ) ) {
return false;
}
return (bool) $supports;
}
}