bookingPage, 'render' ] ) ); add_shortcode( 'us_student_login', self::shortcode( [ $this->loginPage, 'render' ] ) ); add_shortcode( 'us_student_register', self::shortcode( [ $this->registrationPage, 'render' ] ) ); add_shortcode( 'us_group_classes', self::shortcode( [ $this->groupClassPage, 'render' ] ) ); // Process registration submissions before output so the invite branch's // auth cookie is actually sent (render() runs too late, during the_content). add_action( 'template_redirect', [ $this->registrationPage, 'maybeHandleSubmit' ] ); add_action( 'template_redirect', [ $this->registrationPage, 'maybeRedirectToRegistrationPage' ] ); add_action( 'wp_enqueue_scripts', [ $this, 'enqueueAssets' ] ); } /** * Wraps a page renderer so bare shortcode usage is safe: WordPress passes * an empty string, not an array, to the callback when a shortcode is used * without attributes (`shortcode_parse_atts( '' )` returns `''`). * * @param callable(array): string $render * @return \Closure(mixed): string */ private static function shortcode( callable $render ): \Closure { return static fn( mixed $atts ): string => $render( is_array( $atts ) ? $atts : [] ); } public function enqueueAssets(): void { wp_register_style( 'us-scheduler', USC_PLUGIN_URL . 'assets/css/frontend.css', [], USC_VERSION ); $settings = new StudioSettings(); // Stripe.js (loaded from Stripe's CDN per their terms) only when card billing // is available; the payment helper degrades to e-transfer messaging without it. $paymentDeps = []; if ( $settings->isStripeConfigured() ) { // Stripe pins the version in the URL path (/v3/) and forbids self-hosting, // so no query-string version applies here. wp_register_script( 'us-scheduler-stripe', 'https://js.stripe.com/v3/', [], null, true ); // phpcs:ignore WordPress.WP.EnqueuedResourceParameters.MissingVersion $paymentDeps[] = 'us-scheduler-stripe'; } wp_register_script( 'us-scheduler-payment', USC_PLUGIN_URL . 'assets/js/payment.js', $paymentDeps, USC_VERSION, true ); $data = [ 'restUrl' => rest_url( 'us-scheduler/v1/' ), 'nonce' => wp_create_nonce( 'wp_rest' ), 'stripeKey' => $settings->publishableKey(), 'startOfWeek' => Val::int( get_option( 'start_of_week', 1 ) ), // The studio HST rate, so a price quoted to a student on the way in // matches the total they are actually billed. 'taxRate' => $settings->hstRate(), ]; // Attach the shared config to the payment helper so it is defined before the // booking/group scripts (which depend on it) run. wp_localize_script( 'us-scheduler-payment', 'usScheduler', $data ); // Price formatting and the pay agreement, shared by booking and enrolment. wp_register_script( 'us-scheduler-pricing', USC_PLUGIN_URL . 'assets/js/pricing.js', [ 'us-scheduler-payment' ], USC_VERSION, true ); wp_register_script( 'us-scheduler', USC_PLUGIN_URL . 'assets/js/booking.js', [ 'us-scheduler-pricing' ], USC_VERSION, true ); wp_register_script( 'us-scheduler-group', USC_PLUGIN_URL . 'assets/js/group-classes.js', [ 'us-scheduler-pricing' ], USC_VERSION, true ); // Progressive enhancement for the two-step registration form (no dependencies). wp_register_script( 'us-scheduler-register', USC_PLUGIN_URL . 'assets/js/register.js', [], USC_VERSION, true ); } }