*/ public static function run_statuses() { return self::filtered( 'run_status', array( RunStatus::DRAFT => __( 'Draft', 'recast-subscriptions' ), RunStatus::RESOLVING => __( 'Collecting subscriptions', 'recast-subscriptions' ), RunStatus::PREVIEWING => __( 'Building preview', 'recast-subscriptions' ), RunStatus::PREVIEWED => __( 'Preview ready', 'recast-subscriptions' ), RunStatus::APPLYING => __( 'Applying', 'recast-subscriptions' ), RunStatus::PAUSED => __( 'Paused', 'recast-subscriptions' ), RunStatus::CANCELLING => __( 'Stopping', 'recast-subscriptions' ), RunStatus::CANCELLED => __( 'Stopped', 'recast-subscriptions' ), // Not stored: shown for a cancelled batch that never changed a subscription. 'discarded' => __( 'Discarded', 'recast-subscriptions' ), RunStatus::APPLIED => __( 'Applied', 'recast-subscriptions' ), RunStatus::APPLIED_WITH_ISSUES => __( 'Applied with skips', 'recast-subscriptions' ), RunStatus::UNDONE => __( 'Undone', 'recast-subscriptions' ), RunStatus::PARTIALLY_UNDONE => __( 'Partly undone', 'recast-subscriptions' ), RunStatus::FAILED => __( 'Failed', 'recast-subscriptions' ), RunStatus::EXPIRED => __( 'Preview expired', 'recast-subscriptions' ), ) ); } /** * Item (one subscription in a batch) status labels. * * @return array */ public static function item_statuses() { return self::filtered( 'item_status', array( ItemStatus::PENDING => __( 'Waiting', 'recast-subscriptions' ), ItemStatus::READY => __( 'Will change', 'recast-subscriptions' ), ItemStatus::NO_CHANGE => __( 'No change', 'recast-subscriptions' ), ItemStatus::INVALID => __( 'Skipped', 'recast-subscriptions' ), ItemStatus::CLAIMED => __( 'In progress', 'recast-subscriptions' ), ItemStatus::APPLIED => __( 'Applied', 'recast-subscriptions' ), ItemStatus::STALE => __( 'Changed after preview', 'recast-subscriptions' ), ItemStatus::FAILED => __( 'Failed', 'recast-subscriptions' ), ItemStatus::SKIPPED => __( 'Skipped', 'recast-subscriptions' ), ItemStatus::REVERTED => __( 'Undone', 'recast-subscriptions' ), ) ); } /** * Export status labels. * * @return array */ public static function export_statuses() { return self::filtered( 'export_status', array( ExportRepository::STATUS_PENDING => __( 'Waiting', 'recast-subscriptions' ), ExportRepository::STATUS_RUNNING => __( 'Exporting', 'recast-subscriptions' ), ExportRepository::STATUS_READY => __( 'Ready', 'recast-subscriptions' ), ExportRepository::STATUS_FAILED => __( 'Failed', 'recast-subscriptions' ), ExportRepository::STATUS_CANCELLED => __( 'Stopped', 'recast-subscriptions' ), ExportRepository::STATUS_EXPIRED => __( 'Expired', 'recast-subscriptions' ), ) ); } /** * Short labels for warning and skip codes (shown as badges and in counts). * * @return array */ public static function warnings() { return self::filtered( 'warning', array( 'pending_switch' => __( 'Switch pending', 'recast-subscriptions' ), 'coupon_present' => __( 'Coupon applied', 'recast-subscriptions' ), 'tax_recalculated' => __( 'Tax recalculated', 'recast-subscriptions' ), 'synced_product' => __( 'Renewal day is synchronised', 'recast-subscriptions' ), 'some_items_out_of_bounds' => __( 'Some items outside the price limits', 'recast-subscriptions' ), 'price_out_of_bounds' => __( 'Price outside the limits', 'recast-subscriptions' ), 'no_target_items' => __( 'No matching items', 'recast-subscriptions' ), 'status_not_allowed' => __( 'Status not included', 'recast-subscriptions' ), 'transition_not_allowed' => __( 'Status change not permitted', 'recast-subscriptions' ), 'status_not_restorable' => __( 'Status cannot be restored', 'recast-subscriptions' ), 'too_soon' => __( 'Date too soon', 'recast-subscriptions' ), 'date_order' => __( 'Dates out of order', 'recast-subscriptions' ), 'bad_datetime' => __( 'Date not valid', 'recast-subscriptions' ), 'date_locked' => __( 'Date cannot be changed', 'recast-subscriptions' ), 'no_next_payment' => __( 'No next payment', 'recast-subscriptions' ), 'no_end_date' => __( 'No end date', 'recast-subscriptions' ), 'no_running_trial' => __( 'No trial in progress', 'recast-subscriptions' ), 'next_payment_in_past' => __( 'Next payment in the past', 'recast-subscriptions' ), 'pending_cancel' => __( 'Pending cancellation', 'recast-subscriptions' ), 'no_gateway' => __( 'No payment method for automatic renewal', 'recast-subscriptions' ), 'gateway_unavailable' => __( 'Payment method not available', 'recast-subscriptions' ), 'gateway_requires_payment_meta' => __( 'Payment method needs a saved card', 'recast-subscriptions' ), 'gateway_no_amount_changes' => __( 'Payment method does not permit price changes', 'recast-subscriptions' ), 'gateway_no_schedule_changes' => __( 'Payment method does not permit date changes', 'recast-subscriptions' ), 'product_missing' => __( 'Product not found', 'recast-subscriptions' ), 'target_not_subscription' => __( 'New product is not a subscription product', 'recast-subscriptions' ), 'billing_schedule_mismatch' => __( 'New product bills on another schedule', 'recast-subscriptions' ), 'target_no_price' => __( 'New product has no price', 'recast-subscriptions' ), 'target_already_on_subscription' => __( 'New product already on the subscription', 'recast-subscriptions' ), 'original_product_missing' => __( 'Original product deleted', 'recast-subscriptions' ), 'meta_denied' => __( 'Protected field', 'recast-subscriptions' ), 'meta_not_scalar' => __( 'Field has more than one value', 'recast-subscriptions' ), 'source_operation_missing' => __( 'Original change not available', 'recast-subscriptions' ), 'source_missing' => __( 'Original batch not available', 'recast-subscriptions' ), 'item_missing' => __( 'Line item missing', 'recast-subscriptions' ), 'journal_purged' => __( 'History deleted', 'recast-subscriptions' ), 'not_applied' => __( 'Not applied', 'recast-subscriptions' ), 'changed_since_apply' => __( 'Changed after apply', 'recast-subscriptions' ), 'renewal_after_apply' => __( 'Renewed after apply', 'recast-subscriptions' ), 'confirm_status_cancel_or_expire' => __( 'Cancels or ends subscriptions', 'recast-subscriptions' ), 'confirm_next_payment_within_48h' => __( 'Next payment in less than 48 hours', 'recast-subscriptions' ), 'confirm_immediate_charge' => __( 'Charges the customer now', 'recast-subscriptions' ), 'confirm_undo_with_drift' => __( 'Changed after apply', 'recast-subscriptions' ), ) ); } /** * Full-sentence labels for the confirmation checkboxes shown before apply. * * @return array */ public static function confirmations() { return self::filtered( 'confirmation', array( Thresholds::COUNT_OVER_100 => __( 'This batch changes more than 100 subscriptions.', 'recast-subscriptions' ), Thresholds::REVENUE_DELTA_OVER_PCT => __( 'Recurring revenue changes by more than 10 %.', 'recast-subscriptions' ), Thresholds::REVENUE_DELTA_OVER_ABS => __( 'Recurring revenue changes by more than 1,000.', 'recast-subscriptions' ), 'confirm_status_cancel_or_expire' => __( 'This batch cancels or ends subscriptions. Customers stop paying.', 'recast-subscriptions' ), 'confirm_next_payment_within_48h' => __( 'Some next payments are less than 48 hours away.', 'recast-subscriptions' ), 'confirm_immediate_charge' => __( 'Recast will charge some customers as soon as it applies the batch.', 'recast-subscriptions' ), 'confirm_undo_with_drift' => __( 'Some subscriptions changed after apply. Recast will overwrite those changes.', 'recast-subscriptions' ), ) ); } /** * Label for a batch status. * * @param string $code Code. * @return string */ public static function run_status( $code ) { return self::lookup( self::run_statuses(), $code ); } /** * Label for an item status. * * @param string $code Code. * @return string */ public static function item_status( $code ) { return self::lookup( self::item_statuses(), $code ); } /** * Label for an export status. * * @param string $code Code. * @return string */ public static function export_status( $code ) { return self::lookup( self::export_statuses(), $code ); } /** * Label for a warning or skip code. * * @param string $code Code. * @return string */ public static function warning( $code ) { $code = (string) $code; if ( 0 === strpos( $code, 'undo_blocked_' ) ) { /* translators: %s: reason */ return sprintf( __( 'Undo blocked: %s', 'recast-subscriptions' ), self::lookup( self::warnings(), substr( $code, strlen( 'undo_blocked_' ) ) ) ); } return self::lookup( self::warnings(), $code ); } /** * Label for a confirmation code. * * @param string $code Code. * @return string */ public static function confirmation( $code ) { return self::lookup( self::confirmations(), $code ); } /** * Everything, keyed for the admin app. * * @return array> */ public static function for_js() { return array( 'runStatus' => self::run_statuses(), 'itemStatus' => self::item_statuses(), 'exportStatus' => self::export_statuses(), 'warning' => self::warnings(), 'confirmation' => self::confirmations(), ); } /** * Readable fallback for codes without a label. * * @param string $code Code. * @return string */ public static function humanize( $code ) { return ucfirst( str_replace( '_', ' ', (string) $code ) ); } /** * Map lookup with fallback. * * @param array $map Map. * @param string $code Code. * @return string */ private static function lookup( array $map, $code ) { $code = (string) $code; return isset( $map[ $code ] ) ? $map[ $code ] : self::humanize( $code ); } /** * Lets extensions add or change labels. * * @param string $kind Map name. * @param array $map Map. * @return array */ private static function filtered( $kind, array $map ) { /** * Filters a label map. * * @param array $map Code => label. * @param string $kind run_status|item_status|export_status|warning|confirmation. */ return (array) apply_filters( 'recast_labels', $map, $kind ); } }