PluginProbe ʕ •ᴥ•ʔ
Tutor LMS – eLearning and online course solution / 2.1.1
Tutor LMS – eLearning and online course solution v2.1.1
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 1.1.0 1.1.1 1.2.0 1.2.1 1.2.11 1.2.12 1.2.13 1.2.20 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 1.7.3 1.7.4 1.7.5 1.7.6 1.7.7 1.7.8 1.7.9 1.8.0 1.8.1 1.8.10 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 1.8.7 1.8.8 1.8.9 1.9.0 1.9.1 1.9.10 1.9.11 1.9.12 1.9.13 1.9.14 1.9.15 1.9.16 1.9.2 1.9.3 1.9.4 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.0.1 2.0.10 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 2.1.0 2.1.1 2.1.10 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.3.0 2.4.0 2.5.0 2.6.0 2.6.1 2.6.2 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 3.0.0 3.0.1 3.0.2 3.1.0 3.2.0 3.2.1 3.2.2 3.2.3 3.3.0 3.3.1 3.4.0 3.4.1 3.4.2 3.5.0 3.6.0 3.6.1 3.6.2 3.6.3 3.6.4 3.7.0 3.7.1 3.7.2 3.7.3 3.7.4 3.8.0 3.8.1 3.8.2 3.8.3 3.9.0 3.9.1 3.9.10 3.9.2 3.9.3 3.9.4 3.9.5 3.9.6 3.9.7 3.9.8 3.9.9
tutor / models / CourseModel.php
tutor / models Last commit date
CourseModel.php 3 years ago LessonModel.php 3 years ago QuizModel.php 3 years ago WithdrawModel.php 3 years ago
CourseModel.php
326 lines
1 <?php
2 namespace Tutor\Models;
3
4 use Tutor\Helpers\QueryHelper;
5
6 /**
7 * Class CourseModel
8 * @since 2.0.6
9 */
10 class CourseModel {
11 /**
12 * WordPress course type name
13 * @var string
14 */
15 const POST_TYPE = 'courses';
16
17 const STATUS_PUBLISH = 'publish';
18 const STATUS_DRAFT = 'draft';
19 const STATUS_AUTO_DRAFT = 'auto-draft';
20 const STATUS_PENDING = 'pending';
21
22 /**
23 * Course record count
24 *
25 * @return int
26 *
27 * @since 2.0.7
28 */
29 public static function count( $status = self::STATUS_PUBLISH ) {
30 $count_obj = wp_count_posts( self::POST_TYPE );
31 if ( 'all' === $status ) {
32 return array_sum( (array) $count_obj );
33 }
34
35 return (int) $count_obj->{$status};
36 }
37
38 /**
39 * Get courses
40 *
41 * @param array $excludes exclude course ids
42 *
43 * @return array|null|object
44 *
45 * @since 1.0.0
46 */
47 public function get_courses( $excludes = array(), $post_status = array( 'publish' ) ) {
48 global $wpdb;
49
50 $excludes = (array) $excludes;
51 $exclude_query = '';
52
53 if ( count( $excludes ) ) {
54 $exclude_query = implode( "','", $excludes );
55 }
56
57 $post_status = array_map(
58 function ( $element ) {
59 return "'" . $element . "'";
60 },
61 $post_status
62 );
63
64 $post_status = implode( ',', $post_status );
65 $course_post_type = tutor()->course_post_type;
66
67 $query = $wpdb->get_results(
68 $wpdb->prepare(
69 "SELECT ID,
70 post_author,
71 post_title,
72 post_name,
73 post_status,
74 menu_order
75 FROM {$wpdb->posts}
76 WHERE post_status IN ({$post_status})
77 AND ID NOT IN('$exclude_query')
78 AND post_type = %s;
79 ",
80 $course_post_type
81 )
82 );
83
84 return $query;
85 }
86
87 /**
88 * Get courses for instructors
89 *
90 * @param int $instructor_id Instructor ID
91 *
92 * @return array|null|object
93 *
94 * @since 1.0.0
95 */
96 public function get_courses_for_instructors( $instructor_id = 0 ) {
97 $instructor_id = tutor_utils()->get_user_id( $instructor_id );
98 $course_post_type = tutor()->course_post_type;
99
100 $courses = get_posts(
101 array(
102 'post_type' => $course_post_type,
103 'author' => $instructor_id,
104 'post_status' => array( 'publish', 'pending' ),
105 'posts_per_page' => 5,
106 )
107 );
108
109 return $courses;
110 }
111
112 /**
113 * Mark the course as completed
114 *
115 * @param int $course_id course id which is completed
116 * @param int $user_id student id who completed the course
117 * @return bool
118 *
119 * @since 2.0.7
120 */
121 public static function mark_course_as_completed( $course_id, $user_id ) {
122 if ( ! $course_id || ! $user_id ) {
123 return false;
124 }
125
126 do_action( 'tutor_course_complete_before', $course_id );
127
128 /**
129 * Marking course completed at Comment
130 */
131 global $wpdb;
132
133 $date = date( 'Y-m-d H:i:s', tutor_time() );
134
135 // Making sure that, hash is unique
136 do {
137 $hash = substr( md5( wp_generate_password( 32 ) . $date . $course_id . $user_id ), 0, 16 );
138 $hasHash = (int) $wpdb->get_var(
139 $wpdb->prepare(
140 "SELECT COUNT(comment_ID) from {$wpdb->comments}
141 WHERE comment_agent = 'TutorLMSPlugin' AND comment_type = 'course_completed' AND comment_content = %s ",
142 $hash
143 )
144 );
145
146 } while ( $hasHash > 0 );
147
148 $data = array(
149 'comment_post_ID' => $course_id,
150 'comment_author' => $user_id,
151 'comment_date' => $date,
152 'comment_date_gmt' => get_gmt_from_date( $date ),
153 'comment_content' => $hash, // Identification Hash
154 'comment_approved' => 'approved',
155 'comment_agent' => 'TutorLMSPlugin',
156 'comment_type' => 'course_completed',
157 'user_id' => $user_id,
158 );
159
160 $wpdb->insert( $wpdb->comments, $data );
161
162 do_action( 'tutor_course_complete_after', $course_id, $user_id );
163
164 return true;
165 }
166
167 /**
168 * Delete a course by ID
169 *
170 * @param int $post_id course id that need to delete
171 * @return bool
172 *
173 * @since 2.0.9
174 */
175 public static function delete_course( $post_id ) {
176 if ( get_post_type( $post_id ) !== tutor()->course_post_type ) {
177 return false;
178 }
179
180 wp_delete_post( $post_id, true );
181 return true;
182 }
183
184 /**
185 * Get post ids by post type and parent_id
186 *
187 * @since v.1.6.6
188 */
189 private function get_post_ids( $post_type, $post_parent ) {
190 $args = array(
191 'fields' => 'ids',
192 'post_type' => $post_type,
193 'post_parent' => $post_parent,
194 'post_status' => 'any',
195 'posts_per_page' => -1,
196 );
197 return get_posts( $args );
198 }
199
200 /**
201 * Delete course data when permanently deleting a course.
202 *
203 * @return bool
204 *
205 * @since v.1.6.6
206 * @updated 2.0.9
207 */
208 public function delete_course_data( $post_id ) {
209 $course_post_type = tutor()->course_post_type;
210 if ( get_post_type( $post_id ) !== $course_post_type ) {
211 return false;
212 }
213
214 global $wpdb;
215
216 $lesson_post_type = tutor()->lesson_post_type;
217 $assignment_post_type = tutor()->assignment_post_type;
218 $quiz_post_type = tutor()->quiz_post_type;
219
220 $topic_ids = $this->get_post_ids( 'topics', $post_id );
221
222 // Course > Topic > ( Lesson | Quiz | Assignment )
223 if ( ! empty( $topic_ids ) ) {
224 foreach ( $topic_ids as $topic_id ) {
225 $content_post_type = array( $lesson_post_type, $assignment_post_type, $quiz_post_type );
226 $topic_content_ids = $this->get_post_ids( $content_post_type, $topic_id );
227
228 foreach ( $topic_content_ids as $content_id ) {
229 /**
230 * Delete Quiz data
231 */
232 if ( get_post_type( $content_id ) === 'tutor_quiz' ) {
233 $wpdb->delete( $wpdb->prefix . 'tutor_quiz_attempts', array( 'quiz_id' => $content_id ) );
234 $wpdb->delete( $wpdb->prefix . 'tutor_quiz_attempt_answers', array( 'quiz_id' => $content_id ) );
235
236 $questions_ids = $wpdb->get_col( $wpdb->prepare( "SELECT question_id FROM {$wpdb->prefix}tutor_quiz_questions WHERE quiz_id = %d ", $content_id ) );
237 if ( is_array( $questions_ids ) && count( $questions_ids ) ) {
238 $in_question_ids = "'" . implode( "','", $questions_ids ) . "'";
239 $wpdb->query( "DELETE FROM {$wpdb->prefix}tutor_quiz_question_answers WHERE belongs_question_id IN({$in_question_ids}) " );
240 }
241 $wpdb->delete( $wpdb->prefix . 'tutor_quiz_questions', array( 'quiz_id' => $content_id ) );
242 }
243
244 /**
245 * Delete assignment data ( Assignments, Assignment Submit, Assignment Evalutation )
246 * @since 2.0.9
247 */
248 if ( get_post_type( $content_id ) === $assignment_post_type ) {
249 QueryHelper::delete_comment_with_meta( array( 'comment_type' => 'tutor_assignment', 'comment_post_ID' => $content_id ) );
250 }
251
252 wp_delete_post( $content_id, true );
253
254 }
255
256 // Delete zoom meeting.
257 $wpdb->delete(
258 $wpdb->posts,
259 array(
260 'post_parent' => $topic_id,
261 'post_type' => 'tutor_zoom_meeting'
262 )
263 );
264
265 /**
266 * Delete Google Meet Record Related to Course Topic
267 * @since 2.1.0
268 */
269 $wpdb->delete(
270 $wpdb->posts,
271 array(
272 'post_parent' => $topic_id,
273 'post_type' => 'tutor-google-meet'
274 )
275 );
276
277 wp_delete_post( $topic_id, true );
278 }
279 }
280
281 $child_post_ids = $this->get_post_ids( array( 'tutor_announcements', 'tutor_enrolled', 'tutor_zoom_meeting', 'tutor-google-meet' ), $post_id );
282 if ( ! empty( $child_post_ids ) ) {
283 foreach ( $child_post_ids as $child_post_id ) {
284 wp_delete_post( $child_post_id, true );
285 }
286 }
287
288 /**
289 * Delete earning, gradebook result, course complete data
290 *
291 * @since 2.0.9
292 */
293 $wpdb->delete( $wpdb->prefix . 'tutor_earnings', array( 'course_id' => $post_id ) );
294 $wpdb->delete( $wpdb->prefix . 'tutor_gradebooks_results', array( 'course_id' => $post_id ) );
295 $wpdb->delete( $wpdb->comments, array( 'comment_type' => 'course_completed', 'comment_post_ID' => $post_id ) );
296
297 /**
298 * Delete onsite notification record & _tutor_instructor_course_id user meta
299 * @since 2.1.0
300 */
301 $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}tutor_notifications WHERE post_id=%d AND type IN ('Announcements','Q&A','Enrollments')", $post_id ) );
302 $wpdb->delete( $wpdb->usermeta, array( 'meta_key' => '_tutor_instructor_course_id', 'meta_value' => $post_id ) );
303
304 /**
305 * Delete Course rating and review
306 * @since 2.0.9
307 */
308 QueryHelper::delete_comment_with_meta( array( 'comment_type' => 'tutor_course_rating', 'comment_post_ID' => $post_id ) );
309
310 /**
311 * Delete Q&A and its status ( read, replied etc )
312 * @since 2.0.9
313 */
314 QueryHelper::delete_comment_with_meta( array( 'comment_type' => 'tutor_q_and_a', 'comment_post_ID' => $post_id ) );
315
316 /**
317 * Delete caches
318 */
319 $attempt_cache = new \Tutor\Cache\QuizAttempts();
320 if ( $attempt_cache->has_cache() ) {
321 $attempt_cache->delete_cache();
322 }
323
324 return true;
325 }
326 }