course_id ] = true; $this->places[ $e->course_id ] = $e->places_left; } if ( array() === $courses ) { return; } $ids = array_keys( $courses ); $rows = Db::rows( 'SELECT /* outside-tx */ * FROM %i WHERE state = %d AND target_type IN (%d, %d, %d) AND target_id IN (' . implode( ',', array_fill( 0, count( $ids ), '%d' ) ) . ') ORDER BY target_id, target_type, variation_id DESC, id', array_merge( array( Db::table( 'offers' ), OfferState::ACTIVE->value, OfferTarget::COURSE->value, OfferTarget::SECTIONS->value, OfferTarget::LESSON->value ), $ids ) ); $lines = array(); foreach ( $rows as $row ) { $offer = Offer::from_row( $row ); $this->offers[ $offer->target_id ][] = $offer; if ( OfferTarget::COURSE === $offer->target_type ) { $lines[] = $offer->variation_id > 0 ? $offer->variation_id : $offer->product_id; } } $lines = array_values( array_unique( $lines ) ); if ( array() === $lines || ! function_exists( 'wc_get_products' ) ) { return; } $products = wc_get_products( array( 'include' => $lines, 'type' => array_merge( array_keys( wc_get_product_types() ), array( 'variation' ) ), 'status' => array( 'publish', 'private' ), 'limit' => count( $lines ), ) ); foreach ( is_array( $products ) ? $products : array() as $product ) { if ( $product instanceof \WC_Product ) { $this->products[ (int) $product->get_id() ] = $product; } } } public function has_offer( Event $e ): bool { return array() !== ( $this->offers[ $e->course_id ] ?? array() ); } public function button( Event $e, int $user_id ): string { if ( ! $this->has_offer( $e ) ) { return ''; } $key = $e->course_id . ':' . $e->session->unit_id . ':live'; if ( ! isset( $this->buttons[ $key ] ) ) { $answer = array( $this, 'answer' ); add_filter( 'rooster_lms_buy_button_html', $answer, 9, 6 ); $free = array( BuyButton::class, 'buy_button_filter' ); $rests = class_exists( BuyButton::class ) && 10 === has_filter( 'rooster_lms_buy_button_html', $free ); if ( $rests ) { remove_filter( 'rooster_lms_buy_button_html', $free, 10 ); } $this->buttons[ $key ] = (string) apply_filters( 'rooster_lms_buy_button_html', '', $e->course_id, $e->session->unit_id, $user_id, $e->id(), 'live' ); if ( $rests ) { add_filter( 'rooster_lms_buy_button_html', $free, 10, 6 ); } remove_filter( 'rooster_lms_buy_button_html', $answer, 9 ); } return $this->buttons[ $key ]; } public function answer( $html, $course_id = 0, $unit_id = 0, $user_id = 0, $occurrence_id = 0, $window = '' ): string { unset( $unit_id, $user_id, $occurrence_id, $window ); $html = (string) $html; if ( '' !== $html || ! class_exists( BuyButton::class ) || ! function_exists( 'wc_get_checkout_url' ) ) { return $html; } $product = $this->product( (int) $course_id ); if ( null === $product ) { return ''; } if ( 0 === ( $this->places[ (int) $course_id ] ?? null ) ) { return '

' . esc_html__( 'No places left.', 'rooster-lms' ) . '

'; } return '
' . '

' . wp_kses_post( $product->get_price_html() ) . '

' . '' . esc_html__( 'Buy now', 'rooster-lms' ) . '' . '
'; } private function buy_url( \WC_Product $product ): string { if ( $product instanceof \WC_Product_Variation ) { return BuyButton::buy_url( $product ); } $this->checkout ??= (string) wc_get_checkout_url(); return add_query_arg( 'add-to-cart', $product->get_id(), $this->checkout ); } public function price( Event $e ): ?array { $product = $this->product( $e->course_id ); if ( null === $product || ! function_exists( 'wc_get_price_to_display' ) ) { return null; } return array( 'price' => number_format( (float) wc_get_price_to_display( $product ), wc_get_price_decimals(), '.', '' ), 'currency' => (string) get_woocommerce_currency(), ); } private function product( int $course_id ): ?\WC_Product { if ( array() === $this->products ) { return null; } foreach ( $this->offers[ $course_id ] ?? array() as $offer ) { if ( OfferTarget::COURSE !== $offer->target_type ) { continue; } $product = $this->products[ $offer->variation_id > 0 ? $offer->variation_id : $offer->product_id ] ?? null; if ( $product instanceof \WC_Product && $product->is_purchasable() ) { return $product; } } return null; } }