Diff: STRATO-apps/wordpress_03/app/wp-content/plugins/tutor-pro/gift-course/GiftCourse.php

Keine Baseline-Datei – Diff nur gegen leer.
Zur Liste
1 -
1 + <?php
2 + /**
3 + * Handle Gift Course
4 + *
5 + * @package TutorPro\GiftCourse
6 + * @author Themeum <support@themeum.com>
7 + * @link https://themeum.com
8 + * @since 3.8.0
9 + */
10 +
11 + namespace TutorPro\GiftCourse;
12 +
13 + use TUTOR\Course;
14 + use Tutor\Helpers\DateTimeHelper;
15 + use Tutor\Helpers\HttpHelper;
16 + use TUTOR\Icon;
17 + use TUTOR\Input;
18 + use Tutor\Models\CourseModel;
19 + use Tutor\Traits\JsonResponse;
20 + use TUTOR_ENROLLMENTS\Enrollments;
21 +
22 + if ( ! defined( 'ABSPATH' ) ) {
23 + exit;
24 + }
25 +
26 + /**
27 + * Class Course Coming Soon
28 + */
29 + class GiftCourse {
30 +
31 + use JsonResponse;
32 +
33 + /**
34 + * Store gift course details in this meta key.
35 + *
36 + * @since 3.8.0
37 + */
38 + const GIFT_FLAG_META = 'tutor_gift';
39 + const GIFT_DATA_META = 'tutor_gift_payload';
40 + const GIFT_STATUS_META = 'tutor_gift_status';
41 +
42 + /**
43 + * Gift status
44 + *
45 + * @since 3.8.0
46 + */
47 + const GIFT_STATUS_PROCESSING = 'processing';
48 + const GIFT_STATUS_SCHEDULED = 'scheduled';
49 + const GIFT_STATUS_SENT = 'sent';
50 + const GIFT_STATUS_RECEIVED = 'received';
51 +
52 + const GIFT_SENT_AT_META = 'tutor_gift_sent_at';
53 + const GIFT_RECEIVED_AT_META = 'tutor_gift_received_at';
54 +
55 + /**
56 + * Register hooks.
57 + *
58 + * @since 3.3.0
59 + */
60 + public function __construct() {
61 + add_action( 'tutor_course/single/entry/after', array( $this, 'add_gift_this_course_button' ) );
62 + add_action( 'tutor_before_dashboard_content', array( $this, 'gift_course_banner_template' ) );
63 + add_action( 'tutor_cart_item_badge', array( $this, 'add_cart_item_gift_badge' ) );
64 + add_action( 'wp_ajax_tutor_pro_gift_proceed_to_checkout', array( $this, 'ajax_gift_proceed_to_checkout' ) );
65 + add_filter( 'tutor_enrollment_buttons', array( $this, 'filter_enrollment_buttons' ), 10, 3 );
66 + }
67 +
68 + /**
69 + * Add gift this course button to the single course entry box.
70 + *
71 + * @since 3.8.0
72 + *
73 + * @param int $course_id the course id.
74 + *
75 + * @return void
76 + */
77 + public function add_gift_this_course_button( $course_id ) {
78 + if ( ! $this->can_gift_course( $course_id ) ) {
79 + return;
80 + }
81 +
82 + ?>
83 + <button class="tutor-btn tutor-btn-primary tutor-btn-gift tutor-btn-lg tutor-btn-block tutor-my-12 <?php echo is_user_logged_in() ? '' : 'tutor-open-login-modal'; ?>" <?php echo is_user_logged_in() ? 'data-tutor-modal-target="tutor-gift-this-course-modal"' : ''; ?>>
84 + <?php tutor_utils()->render_svg_icon( Icon::GIFT, 24, 24 ); ?>
85 + <?php esc_html_e( 'Gift this Course', 'tutor-pro' ); ?>
86 + </button>
87 + <?php
88 +
89 + if ( is_user_logged_in() ) {
90 + tutor_load_template(
91 + 'single.course.gift-this-course-modal',
92 + array( 'course_id' => $course_id ),
93 + true
94 + );
95 + }
96 + }
97 +
98 + /**
99 + * Add gift this course banner to the dashboard.
100 + *
101 + * @since 3.8.0
102 + *
103 + * @return void
104 + */
105 + public function gift_course_banner_template() {
106 + $user_id = get_current_user_id();
107 + $gifts = $this->get_gift_courses( $user_id );
108 +
109 + if ( tutor_utils()->count( $gifts ) ) {
110 + foreach ( $gifts as $gift ) {
111 + $reference_id = $gift->reference_id;
112 + $payload = json_decode( $gift->payload );
113 + $course_id = $payload->course_id;
114 + if ( $this::can_open_gift( $gift ) ) {
115 + tutor_load_template(
116 + 'dashboard.gift-course',
117 + compact( 'reference_id', 'course_id' ),
118 + true
119 + );
120 + }
121 + }
122 + }
123 + }
124 +
125 + /**
126 + * Add gift badge to checkout course item
127 + *
128 + * @since 3.8.0
129 + *
130 + * @param object $course the course.
131 + *
132 + * @return void
133 + */
134 + public function add_cart_item_gift_badge( $course ) {
135 + if ( ! $this->is_gift_course_in_cart( $course->ID ) ) {
136 + return;
137 + }
138 +
139 + ?>
140 + <span class="tutor-checkout-gift-course-badge">
141 + <?php tutor_utils()->render_svg_icon( Icon::GIFT, 16, 16 ); ?>
142 + <?php esc_html_e( 'Gift', 'tutor-pro' ); ?>
143 + </span>
144 + <?php
145 + }
146 +
147 + /**
148 + * Process gift course form to proceed to checkout
149 + *
150 + * @since 3.8.0
151 + *
152 + * @return void send wp_json response
153 + */
154 + public function ajax_gift_proceed_to_checkout() {
155 + tutor_utils()->checking_nonce();
156 +
157 + //phpcs:ignore
158 + $gift_form_data = Input::sanitize_array( $_POST, array( 'message' => 'esc_textarea' ) );
159 + $course_id = (int) $gift_form_data['course_id'];
160 +
161 + if ( tutor_is_item_in_cart( $course_id ) ) {
162 + $this->response_bad_request(
163 + __( 'This course is already in your cart and cannot be gifted.', 'tutor-pro' )
164 + );
165 + }
166 +
167 + $user = get_user_by( 'email', $gift_form_data['recipient_email'] );
168 + if ( $user && tutor_utils()->is_enrolled( $course_id, $user->ID ) ) {
169 + $this->response_bad_request(
170 + __( 'The recipient is already enrolled in this course.', 'tutor-pro' )
171 + );
172 + }
173 +
174 + $gift_data = (object) array(
175 + 'reference_id' => 'gift_' . bin2hex( random_bytes( 8 ) ),
176 + 'recipient_name' => $gift_form_data['recipient_name'],
177 + 'recipient_email' => $gift_form_data['recipient_email'],
178 + 'course_id' => $course_id,
179 + 'purchaser_id' => get_current_user_id(),
180 + 'course_title' => get_the_title( $course_id ),
181 + 'scheduled_at_gmt' => $gift_form_data['datetime'],
182 + 'message' => $gift_form_data['message'],
183 + 'notify_me' => (int) $gift_form_data['notify_me'],
184 + );
185 +
186 + $monetization = tutor_utils()->get_option( 'monetize_by' );
187 + try {
188 + $proceeder = GiftProceedFactory::get_proceeder( $monetization );
189 + $checkout_url = $proceeder->proceed_to_checkout( $gift_data );
190 +
191 + $this->json_response(
192 + __( 'Success', 'tutor-pro' ),
193 + array( 'url' => $checkout_url )
194 + );
195 + } catch ( \Throwable $th ) {
196 + $this->json_response(
197 + $th->getMessage(),
198 + null,
199 + HttpHelper::STATUS_BAD_REQUEST
200 + );
201 + }
202 + }
203 +
204 + /**
205 + * Check whether this course is gift-able
206 + *
207 + * @since 3.8.0
208 + *
209 + * @param integer $course_id Course to check against a course.
210 + *
211 + * @return boolean
212 + */
213 + public static function can_gift_course( int $course_id ): bool {
214 + $course = get_post( $course_id );
215 +
216 + // Show gift course button only for published courses.
217 + if ( CourseModel::STATUS_PUBLISH !== $course->post_status ) {
218 + return false;
219 + }
220 +
221 + // Handle free courses.
222 + if ( ! tutor_utils()->is_course_purchasable( $course_id ) ) {
223 + return false;
224 + }
225 +
226 + // Handle enrollment periods settings.
227 + if ( tutor_utils()->is_addon_enabled( 'enrollments' ) ) {
228 + $enrollment = new Enrollments();
229 + list( $pause_enrollment, $course_enrollment_period, $enrollment_starts_at, $enrollment_ends_at ) = array_values( $enrollment->get_course_enrollment_settings( $course_id ) );
230 +
231 + if ( 'yes' === $pause_enrollment ) {
232 + return false;
233 + }
234 +
235 + if ( 'yes' === $course_enrollment_period ) {
236 + if ( $enrollment_starts_at && time() < strtotime( $enrollment_starts_at ) ) {
237 + return false;
238 + }
239 +
240 + if ( $enrollment_ends_at && time() > strtotime( $enrollment_ends_at ) ) {
241 + return false;
242 + }
243 + }
244 + }
245 +
246 + // Handle enrollment booked coursed.
247 + if ( tutor_utils()->is_course_fully_booked( $course_id ) ) {
248 + return false;
249 + }
250 +
251 + // Handle course selling options.
252 + $course_selling_option = Course::get_selling_option( $course_id );
253 + if ( in_array( $course_selling_option, array( Course::SELLING_OPTION_SUBSCRIPTION, Course::SELLING_OPTION_MEMBERSHIP ), true ) ) {
254 + return false;
255 + }
256 +
257 + return apply_filters( 'tutor_can_gift_course', true, $course_id );
258 + }
259 +
260 + /**
261 + * Check if the items is for gift
262 + *
263 + * @since 3.8.0
264 + *
265 + * @param object|integer $item_id Order Item id or item object.
266 + *
267 + * @return object|boolean Item object if exist or false
268 + */
269 + public static function is_gift_item( $item_id ) {
270 + try {
271 + $proceeder = self::get_gift_proceeder();
272 + return $proceeder->is_gift_item( $item_id );
273 + } catch ( \Throwable $th ) {
274 + return false;
275 + }
276 + }
277 +
278 + /**
279 + * Get gift data by course id
280 + *
281 + * @since 3.8.0
282 + *
283 + * @param mixed $reference_id Gift reference id.
284 + * @param bool $details Whether to return gift details or not.
285 + *
286 + * @return mixed false|object
287 + */
288 + public static function get_gift_data_by_reference_id( $reference_id, $details = false ) {
289 + $where = array(
290 + 'reference_id' => $reference_id,
291 + );
292 +
293 + $gift_data = ( new GiftScheduler() )->get( $where );
294 + if ( ! $gift_data ) {
295 + return false;
296 + }
297 +
298 + return $details ? $gift_data : json_decode( $gift_data->payload );
299 + }
300 +
301 + /**
302 + * Get gift proceeder
303 + *
304 + * @since 3.8.0
305 + *
306 + * @throws \Throwable If failed to get proceeder.
307 + *
308 + * @return GiftProceeder
309 + */
310 + public static function get_gift_proceeder() {
311 + $monetization = tutor_utils()->get_option( 'monetize_by' );
312 + try {
313 + return GiftProceedFactory::get_proceeder( $monetization );
314 + } catch ( \Throwable $th ) {
315 + throw $th;
316 + }
317 + }
318 +
319 + /**
320 + * Can user open a gift
321 + *
322 + * @since 3.8.0
323 + *
324 + * @param object|int $gift_details Gift details or gift reference id.
325 + *
326 + * @return bool
327 + */
328 + public static function can_open_gift( object $gift_details ): bool {
329 + if ( is_int( $gift_details ) ) {
330 + $gift_details = self::get_gift_data_by_reference_id( $gift_details, true );
331 + }
332 +
333 + if ( ! $gift_details ) {
334 + return false;
335 + }
336 +
337 + $gift_data = json_decode( $gift_details->payload );
338 + if ( ! $gift_data ) {
339 + $error = json_last_error();
340 + return false;
341 + }
342 +
343 + $user = wp_get_current_user();
344 + if ( $gift_data->recipient_email !== $user->user_email ) {
345 + return false;
346 + }
347 +
348 + $course_id = $gift_data->course_id;
349 + $course = get_post( $course_id );
350 + if ( ! $course || CourseModel::STATUS_PUBLISH !== $course->post_status ) {
351 + return false;
352 + }
353 +
354 + if ( GiftScheduler::STATUS_PROCESSED !== $gift_details->status ) {
355 + return false;
356 + }
357 +
358 + return true;
359 + }
360 +
361 + /**
362 + * Get all gift courses of a user that is ready to claim
363 + *
364 + * @since 3.8.0
365 + *
366 + * @param integer $user_id User id to get gift courses.
367 + *
368 + * @return mixed
369 + */
370 + public static function get_gift_courses( int $user_id ) {
371 + return ( new GiftScheduler() )->get_all( array( 'scheduled_for' => $user_id ) );
372 + }
373 +
374 + /**
375 + * Check if the course in cart is for gift
376 + *
377 + * This method will work only if the monetization is by tutor native
378 + *
379 + * @since 3.8.0
380 + *
381 + * @param integer $course_id The course id.
382 + *
383 + * @return bool true|false
384 + */
385 + public static function is_gift_course_in_cart( int $course_id ) {
386 + if ( ! tutor_utils()->is_monetize_by_tutor() ) {
387 + return false;
388 + }
389 +
390 + return ( new NativeGiftProceeder() )->is_gift_course_in_cart( $course_id );
391 + }
392 +
393 + /**
394 + * Filter enrollment buttons to add gift course button
395 + *
396 + * @since 3.9.3
397 + *
398 + * @param object $buttons buttons.
399 + * @param int $course_id course id.
400 + * @param int $user_id user id.
401 + *
402 + * @return object
403 + */
404 + public function filter_enrollment_buttons( $buttons, $course_id, $user_id ) {
405 + $buttons->show_gift_course_btn = false;
406 +
407 + if ( self::can_gift_course( $course_id ) ) {
408 + $buttons->show_gift_course_btn = true;
409 + }
410 +
411 + return $buttons;
412 + }
413 + }
414 +