PluginProbe
Tutor LMS – eLearning and online course solution / 1.8.10
Tutor LMS – eLearning and online course solution v1.8.10
4.0.7 4.0.6 4.0.5 4.0.4 4.0.3 4.0.2 4.0.1 4.0.0 3.9.15 3.9.14 3.9.13 3.9.12 3.9.11 trunk 1.0.0 1.0.0-alpha 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 All 191 releases
← All changes | classes/TutorEDD.php +93 -315 trunk1.8.10 View file →
@@ -1,99 +1,83 @@
1 1 <?php
2 +
2 3 /**
3 - * Integrate EDD
4 - *
5 - * @package Tutor\PaymentIntegration
6 - * @author Themeum <support@themeum.com>
7 - * @link https://themeum.com
8 - * @since 1.0.0
4 + * Tutor Course attachments Main Class
9 5 */
10 6
11 7 namespace TUTOR;
12 8
13 -defined( 'ABSPATH' ) || exit;
9 +if (!defined('ABSPATH'))
10 + exit;
14 11
15 -use Tutor\Helpers\QueryHelper;
16 -use Tutor\Helpers\UrlHelper;
17 -use Tutor\Models\EnrollmentModel;
18 -
19 -/**
20 - * Manage EDD integration
21 - *
22 - * @since 1.0.0
23 - */
24 12 class TutorEDD extends Tutor_Base {
25 13
26 - /**
27 - * Register hooks
28 - *
29 - * @since 1.0.0
30 - */
31 14 public function __construct() {
32 15 parent::__construct();
33 16
34 - add_filter( 'tutor_monetization_options', array( $this, 'tutor_monetization_options' ) );
17 + //add_action('tutor_options_before_tutor_edd', array($this, 'notice_before_option'));
35 18
36 - $monetize_by = tutils()->get_option( 'monetize_by' );
37 - if ( 'edd' !== $monetize_by ) {
19 + //Add Tutor Option
20 + add_filter('tutor_monetization_options', array($this, 'tutor_monetization_options'));
21 + //add_filter('tutor/options/attr', array($this, 'add_options'));
22 +
23 + $monetize_by = tutils()->get_option('monetize_by');
24 +
25 + if ($monetize_by !== 'edd') {
38 26 return;
39 27 }
40 28
41 - $edd_path = WP_PLUGIN_DIR . '/easy-digital-downloads/easy-digital-downloads.php';
42 - register_deactivation_hook( $edd_path, array( $this, 'edd_deactivation_handler' ) );
29 + add_action('add_meta_boxes', array($this, 'register_meta_box'));
30 + add_action('save_post_' . $this->course_post_type, array($this, 'save_course_meta'));
43 31
44 - add_filter( 'tutor_course_sell_by', fn() => 'edd' );
45 - add_action( 'save_post_' . $this->course_post_type, array( $this, 'save_course_meta' ) );
46 -
47 32 /**
48 33 * Is Course Purchasable
49 34 */
50 - add_filter( 'is_course_purchasable', array( $this, 'is_course_purchasable' ), 10, 2 );
51 - add_filter( 'get_tutor_course_price', array( $this, 'get_tutor_course_price' ), 10, 2 );
52 - add_action( 'edd_insert_payment', array( $this, 'edd_order_created' ), 10, 2 );
53 - add_action( 'edd_update_payment_status', array( $this, 'edd_update_payment_status' ), 10, 3 );
35 + add_filter('is_course_purchasable', array($this, 'is_course_purchasable'), 10, 2);
36 + add_filter('get_tutor_course_price', array($this, 'get_tutor_course_price'), 10, 2);
37 + add_filter('tutor_course_sell_by', array($this, 'tutor_course_sell_by'));
54 38
55 - // @since 4.0.0
56 - add_filter( 'tutor_order_history_card_template', fn( $template ) => tutor_get_template( 'dashboard.account.billing.edd-order-history-card' ) );
57 - add_filter( 'tutor_order_history_status_options', array( $this, 'filter_order_history_status_options' ), 10, 2 );
58 - add_filter( 'tutor_get_orders_by_user_id', array( $this, 'filter_tutor_get_orders_by_user_id' ), 10, 3 );
39 + add_action('edd_update_payment_status', array($this, 'edd_update_payment_status'), 10, 3);
59 40 }
60 41
61 - /**
62 - * Handle EDD deactivation.
63 - *
64 - * @since 4.0.0
65 - *
66 - * @return void
67 - */
68 - public function edd_deactivation_handler() {
69 - if ( 'edd' === tutor_utils()->get_option( 'monetize_by' ) ) {
70 - tutor_utils()->update_option( 'monetize_by', 'free' );
42 + public function notice_before_option() {
43 + $has_edd = tutor_utils()->has_edd();
44 + if ($has_edd) {
45 + return;
71 46 }
47 +
48 + ob_start();
49 + ?>
50 + <div class="tutor-notice-warning">
51 + <p>
52 + <?php _e(' Seems like you don’t have <strong>Easy Digital Downloads</strong> plugin installed on your site. In order to use this functionality, you need to have the <strong>Easy Digital Downloads</strong> plugin installed. Get back on this page after installing the plugin and enable the following feature to start selling courses with Tutor.', 'tutor'); ?>
53 + </p>
54 + <p><?php _e('This notice will disappear after activating <strong>EDD</strong>', 'tutor'); ?></p>
55 + </div>
56 + <?php
57 + echo ob_get_clean();
72 58 }
73 59
74 60 /**
75 - * Add Option for tutor
61 + * @param $attr
76 62 *
77 - * @since 1.0.0
63 + * @return mixed
78 64 *
79 - * @param array $attr option attrs.
80 - *
81 - * @return mixed
65 + * Add Option for tutor
82 66 */
83 - public function add_options( $attr ) {
67 + public function add_options($attr) {
84 68 $attr['tutor_edd'] = array(
85 - 'label' => __( 'EDD', 'tutor' ),
69 + 'label' => __('EDD', 'tutor-edd'),
86 70
87 - 'sections' => array(
71 + 'sections' => array(
88 72 'general' => array(
89 - 'label' => __( 'General', 'tutor' ),
90 - 'desc' => __( 'Tutor Course Attachments Settings', 'tutor' ),
73 + 'label' => __('General', 'tutor-edd'),
74 + 'desc' => __('Tutor Course Attachments Settings', 'tutor-edd'),
91 75 'fields' => array(
92 76 'enable_tutor_edd' => array(
93 - 'type' => 'checkbox',
94 - 'label' => __( 'Enable EDD', 'tutor' ),
95 - 'desc' => __( 'This will enable sell your product via EDD', 'tutor' ),
77 + 'type' => 'checkbox',
78 + 'label' => __('Enable EDD', 'tutor'),
79 + 'desc' => __('This will enable sell your product via EDD', 'tutor'),
96 80 ),
97 81 ),
98 82 ),
99 83 ),
@@ -101,300 +85,94 @@
101 85 return $attr;
102 86 }
103 87
104 88 /**
105 - * Returning monetization options
89 + * @param $arr
106 90 *
107 - * @since 1.3.5
91 + * @return mixed
108 92 *
109 - * @param array $arr monetization attrs.
93 + * Returning monetization options
110 94 *
111 - * @return array
95 + * @since v.1.3.5
112 96 */
113 - public function tutor_monetization_options( $arr ) {
97 + public function tutor_monetization_options($arr) {
114 98 $has_edd = tutils()->has_edd();
115 - if ( $has_edd ) {
116 - $arr['edd'] = __( 'Easy Digital Downloads', 'tutor' );
99 + if ($has_edd) {
100 + $arr['edd'] = __('Easy Digital Downloads', 'tutor');
117 101 }
118 102 return $arr;
119 103 }
120 104
105 + public function register_meta_box() {
106 + add_meta_box('tutor-attached-edd-product', __('Add Product', 'tutor'), array($this, 'course_add_product_metabox'), $this->course_post_type, 'advanced', 'high');
107 + }
108 +
121 109 /**
122 - * Save course meta
123 - *
124 - * @since 1.0.0
125 - *
126 - * @param int $post_ID post id.
127 - *
128 - * @return void
110 + * @param $post
111 + * MetaBox for Lesson Modal Edit Mode
129 112 */
130 - public function save_course_meta( $post_ID ) {
113 + public function course_add_product_metabox() {
114 + include tutor()->path . 'views/metabox/course-add-edd-product-metabox.php';
115 + }
131 116
132 - $product_id = Input::post( Course::COURSE_PRODUCT_ID_META, '' );
117 + public function save_course_meta($post_ID) {
118 + $product_id = tutor_utils()->avalue_dot('_tutor_course_product_id', $_POST);
133 119
134 - if ( '-1' !== $product_id ) {
120 + if ($product_id !== '-1') {
135 121 $product_id = (int) $product_id;
136 - if ( $product_id ) {
137 - update_post_meta( $post_ID, Course::COURSE_PRODUCT_ID_META, $product_id );
138 - update_post_meta( $product_id, '_tutor_product', 'yes' );
122 + if ($product_id) {
123 + update_post_meta($post_ID, '_tutor_course_product_id', $product_id);
124 + update_post_meta($product_id, '_tutor_product', 'yes');
139 125 }
140 126 } else {
141 - delete_post_meta( $post_ID, Course::COURSE_PRODUCT_ID_META );
127 + delete_post_meta($post_ID, '_tutor_course_product_id');
142 128 }
143 -
144 - do_action( 'save_tutor_course', $post_ID, get_post( $post_ID ) );
145 129 }
146 130
147 - /**
148 - * Check if course is purchase able
149 - *
150 - * @param bool $bool default value.
151 - * @param int $course_id course id.
152 - *
153 - * @return boolean
154 - */
155 - public function is_course_purchasable( $bool, $course_id ) {
156 - if ( ! tutor_utils()->has_edd() ) {
131 + public function is_course_purchasable($bool, $course_id) {
132 + if (!tutor_utils()->has_edd()) {
157 133 return false;
158 134 }
159 135
160 - $course_id = tutor_utils()->get_post_id( $course_id );
161 - $price_type = tutor_utils()->price_type( $course_id );
162 - $has_product_id = tutor_utils()->get_course_product_id( $course_id );
163 -
164 - if ( Course::PRICE_TYPE_PAID === $price_type && $has_product_id ) {
136 + $course_id = tutor_utils()->get_post_id($course_id);
137 + $has_product_id = get_post_meta($course_id, '_tutor_course_product_id', true);
138 + if ($has_product_id) {
165 139 return true;
166 140 }
167 -
168 141 return false;
169 142 }
170 143
171 - /**
172 - * Get course price
173 - *
174 - * @since 1.0.0
175 - *
176 - * @param string $price course price.
177 - * @param int $course_id course id.
178 - *
179 - * @return mixed
180 - */
181 - public function get_tutor_course_price( $price, $course_id ) {
182 - $product_id = tutor_utils()->get_course_product_id( $course_id );
183 - if ( tutils()->has_edd() ) {
184 - return edd_price( $product_id, false );
185 - }
144 + public function get_tutor_course_price($price, $course_id) {
145 + $product_id = tutor_utils()->get_course_product_id($course_id);
146 +
147 + return edd_price($product_id, false);
186 148 }
187 149
188 - /**
189 - * Prepare enrollment status.
190 - *
191 - * @since 4.0.0
192 - *
193 - * @param string $order_status order status.
194 - *
195 - * @return string
196 - */
197 - private static function prepare_enrollment_status( $order_status ) {
198 - return 'complete' === $order_status
199 - ? EnrollmentModel::STATUS_COMPLETED
200 - : ( 'pending' === $order_status ? EnrollmentModel::STATUS_PENDING : EnrollmentModel::STATUS_CANCEL );
150 + public function tutor_course_sell_by() {
151 + return 'edd';
201 152 }
202 153
203 - /**
204 - * Handle enrollment.
205 - *
206 - * @since 4.0.0
207 - *
208 - * @param int $order_id The order ID.
209 - * @param string $enrollment_type The enrollment type.
210 - * @param string $enrollment_status The enrollment status.
211 - *
212 - * @return void
213 - */
214 - private static function handle_enrollment( int $order_id, string $enrollment_type, string $enrollment_status ): void {
215 - $order = edd_get_order( $order_id );
216 - if ( ! $order || ! is_object( $order ) ) {
154 + public function edd_update_payment_status($payment_id, $new_status, $old_status) {
155 + if ($new_status !== 'publish') {
217 156 return;
218 157 }
219 158
220 - $order_items = edd_get_order_items( array( 'order_id' => $order->id ) );
221 - if ( empty( $order_items ) ) {
222 - return;
223 - }
159 + $payment = new \EDD_Payment($payment_id);
160 + $cart_details = $payment->cart_details;
161 + $user_id = $payment->user_info['id'];
224 162
225 - $user_id = $order->user_id;
163 + if (is_array($cart_details)) {
164 + foreach ($cart_details as $cart_index => $download) {
226 165
227 - foreach ( $order_items as $order_item ) {
228 - $product_id = $order_item->product_id;
229 - $product_has_course = tutor_utils()->product_belongs_with_course( $product_id );
230 -
231 - if ( ! $product_has_course ) {
232 - continue;
233 - }
234 -
235 - $course_id = (int) $product_has_course->post_id;
236 -
237 - if ( 'new' === $enrollment_type ) {
238 - // New enrollment.
239 - add_filter( 'tutor_enroll_data', fn( $data ) => array_merge( $data, array( 'post_status' => $enrollment_status ) ) );
240 - EnrollmentModel::do_enroll( $course_id, $order_id, $user_id );
241 - } else {
242 - // Update enrollment.
243 - $is_enrolled = EnrollmentModel::is_enrolled( $course_id, $user_id, false );
244 - if ( $is_enrolled ) {
245 - EnrollmentModel::update_enrollments( $enrollment_status, array( $is_enrolled->ID ) );
166 + $if_has_course = tutor_utils()->product_belongs_with_course($download['id']);
167 + if ($if_has_course) {
168 + $course_id = $if_has_course->post_id;
169 + $has_any_enrolled = tutor_utils()->has_any_enrolled($course_id, $user_id);
170 + if (!$has_any_enrolled) {
171 + tutor_utils()->do_enroll($course_id, $payment_id, $user_id);
172 + }
246 173 }
247 174 }
175 + tutor_utils()->complete_course_enroll($payment_id);
248 176 }
249 - }
250 -
251 - /**
252 - * Handle enrollment when a new EDD order is created.
253 - *
254 - * Creates enrollment with appropriate status when EDD 3.0+ has fully
255 - * built the order with its items. This avoids the issue where
256 - * cart_details/order_items are empty during the initial
257 - * edd_update_payment_status hook (old_status = 'new').
258 - *
259 - * @since 4.0.0
260 - *
261 - * @param int $order_id The order ID.
262 - * @param array $order_data The order data array containing cart details.
263 - *
264 - * @return void
265 - */
266 - public function edd_order_created( $order_id, $order_data ) {
267 - if ( ! $order_id ) {
268 - return;
269 - }
270 -
271 - $enrollment_status = self::prepare_enrollment_status( $order_data['status'] );
272 - self::handle_enrollment( $order_id, 'new', $enrollment_status );
273 - }
274 -
275 - /**
276 - * Update enrollment status when EDD payment status changes.
277 - *
278 - * Skips the initial order creation (old_status = 'new') since enrollment
279 - * is handled by edd_order_created. Uses EDD 3.0+ API to retrieve order
280 - * items reliably.
281 - *
282 - * @since 1.0.0
283 - * @since 4.0.0 Refactored to use EDD 3.0+ API and skip initial order creation.
284 - *
285 - * @param int $payment_id payment id.
286 - * @param string $new_status payment's new status.
287 - * @param string $old_status payment's old status.
288 - *
289 - * @return void
290 - */
291 - public function edd_update_payment_status( $payment_id, $new_status, $old_status ) {
292 - if ( empty( $new_status ) || ! $payment_id ) {
293 - return;
294 - }
295 -
296 - /**
297 - * If 'new' === $old_status, EDD does not store cart_details.
298 - * So skip the action, as enrollment is handled by edd_order_created method.
299 - *
300 - * @since 4.0.0
301 - */
302 - if ( 'new' === $old_status ) {
303 - return;
304 - }
305 -
306 - $enrollment_status = self::prepare_enrollment_status( $new_status );
307 - self::handle_enrollment( $payment_id, 'update', $enrollment_status );
308 - }
309 -
310 - /**
311 - * Filter order history status options.
312 - *
313 - * @since 4.0.0
314 - *
315 - * @param array $options the status options.
316 - * @param string $seleted the selected status.
317 - *
318 - * @return array<array{label: string, value: string, count: int, url: string, active: bool}>
319 - */
320 - public function filter_order_history_status_options( $options, $seleted ) {
321 - $url = get_pagenum_link();
322 - $user_id = get_current_user_id();
323 -
324 - $statuses = array_merge( array( 'all' => 'All' ), edd_get_payment_statuses() );
325 - $options = array();
326 -
327 - foreach ( $statuses as $key => $status ) {
328 - $params = array(
329 - 'meta_key' => Course::IS_TUTOR_ORDER_FOR_COURSE_META,
330 - 'user_id' => $user_id,
331 - 'status' => $key,
332 - 'count' => true,
333 - );
334 -
335 - $count_query = new \EDD_Payments_Query( $params );
336 - $count = $count_query->get_payments();
337 -
338 - $options[] = array(
339 - 'label' => $status,
340 - 'value' => $key,
341 - 'count' => $count,
342 - 'url' => UrlHelper::add_query_params( $url, array( 'data' => $key ) ),
343 - 'active' => $key === $seleted || ( empty( $key ) && 'all' === $seleted ),
344 - );
345 - }
346 -
347 - return $options;
348 - }
349 -
350 - /**
351 - * Filter tutor get orders by user id.
352 - *
353 - * @since 4.0.0
354 - *
355 - * @param object $data data.
356 - * @param int $user_id the user id.
357 - * @param array $args the query args.
358 - *
359 - * @return object
360 - */
361 - public function filter_tutor_get_orders_by_user_id( $data, $user_id, $args ) {
362 - if ( ! $user_id ) {
363 - return $data;
364 - }
365 -
366 - $status = Input::sanitize( $args['status'] ?? '' );
367 - $start_date = Input::sanitize( $args['start_date'] ?? '' );
368 - $end_date = Input::sanitize( $args['end_date'] ?? '' );
369 - $order = QueryHelper::get_valid_sort_order( $args['order'] ?? 'DESC' );
370 - $limit = intval( $args['limit'] ?? 0 );
371 - $offset = intval( $args['offset'] ?? 0 );
372 -
373 - $params = array(
374 - 'meta_key' => Course::IS_TUTOR_ORDER_FOR_COURSE_META,
375 - 'user' => $user_id,
376 - 'status' => $status,
377 - 'start_date' => $start_date,
378 - 'end_date' => $end_date,
379 - 'limit' => $limit,
380 - 'offset' => $offset,
381 - 'order' => $order,
382 - );
383 -
384 - if ( empty( $status ) || 'all' === $status ) {
385 - unset( $params['status'] );
386 - }
387 -
388 - $edd_query = new \EDD_Payments_Query( $params );
389 - $results = $edd_query->get_payments();
390 -
391 - $params['count'] = true;
392 - $total_count_query = new \EDD_Payments_Query( $params );
393 - $total_count = $total_count_query->get_payments();
394 -
395 - $data->results = $results;
396 - $data->total_count = $total_count;
397 -
398 - return $data;
399 177 }
400 178 }