PluginProbe
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses / 4.4.8
LearnPress – WordPress LMS Plugin for Create and Sell Online Courses v4.4.8
4.4.8 4.4.7 4.4.6 4.4.5 4.4.4 4.4.3 4.4.2 4.4.1 4.4.0 4.3.9.1 4.3.9 4.3.8 4.3.7 4.1.6.9 4.1.6.9.1 4.1.6.9.2 4.1.6.9.3 4.1.6.9.4 4.1.7 4.1.7.1 4.1.7.2 4.1.7.3 4.1.7.3.1 4.1.7.3.2 4.2.0 All 139 releases
← All changes | inc/Models/PostModel.php +621 -630 4.3.9.14.4.8 View file →
@@ -1,630 +1,621 @@
1 -<?php
2 -
3 -/**
4 - * Class Course
5 - * To replace class LP_User_Item
6 - *
7 - * @package LearnPress/Classes
8 - * @version 1.0.8
9 - * @since 4.2.6.9
10 - */
11 -
12 -namespace LearnPress\Models;
13 -
14 -use Exception;
15 -use LearnPress;
16 -use LearnPress\Databases\PostDB;
17 -use LearnPress\Filters\FilterBase;
18 -use LearnPress\Filters\PostFilter;
19 -use LP_Cache;
20 -use LP_Post_Meta_DB;
21 -use LP_Post_Meta_Filter;
22 -use LP_Post_Type_Filter;
23 -
24 -use stdClass;
25 -use Throwable;
26 -use WP_Error;
27 -use WP_Post;
28 -use WP_Term;
29 -
30 -defined( 'ABSPATH' ) || exit();
31 -
32 -class PostModel {
33 - /**
34 - * Auto increment, Primary key
35 - *
36 - * @var int
37 - */
38 - public $ID = 0;
39 - public $post_author = 0;
40 - public $post_date = null;
41 - public $post_date_gmt = null;
42 - public $post_modified = null;
43 - public $post_modified_gmt = null;
44 - public $post_content = '';
45 - public $post_title = '';
46 - public $post_excerpt = '';
47 - public $post_status = '';
48 - public $post_password = '';
49 - public $post_name = '';
50 - public $post_type = 'post';
51 - public $post_parent = 0;
52 - /**
53 - * @var stdClass all meta data
54 - */
55 - public $meta_data = null;
56 - /**
57 - * @var stdClass all meta data
58 - */
59 - public $is_got_meta_data;
60 - /**
61 - * @var string only for set same property with class WP_Post
62 - */
63 - public $filter;
64 -
65 - const STATUS_PUBLISH = 'publish';
66 - const STATUS_TRASH = 'trash';
67 - const STATUS_DRAFT = 'draft';
68 - const STATUS_PRIVATE = 'private';
69 - const STATUS_PENDING = 'pending';
70 - const STATUS_FEATURE = 'future';
71 - const STATUS_AUTO_DRAFT = 'auto-draft';
72 - const VISIBILITY_PASSWORD = 'password';
73 -
74 - /**
75 - * If data get from database, map to object.
76 - * Else create new object to save data to database.
77 - *
78 - * @param array|object|mixed $data
79 - */
80 - public function __construct( $data = null ) {
81 - if ( $data ) {
82 - $this->map_to_object( $data );
83 - }
84 -
85 - if ( is_null( $this->meta_data ) ) {
86 - $this->meta_data = new stdClass();
87 - }
88 - }
89 -
90 - /**
91 - * Get user model
92 - *
93 - * @return false|UserModel
94 - * @since 4.2.6.9
95 - * @version 1.0.1
96 - */
97 - public function get_author_model() {
98 - if ( ! empty( $this->post_author ) ) {
99 - $author_id = $this->post_author;
100 - } else {
101 - $author_id = get_post_field( 'post_author', $this );
102 - }
103 -
104 - return UserModel::find( $author_id, true );
105 - }
106 -
107 - /**
108 - * Map array, object data to PostModel.
109 - * Use for data get from database.
110 - *
111 - * @param array|object|mixed $data
112 - *
113 - * @return PostModel|static
114 - */
115 - public function map_to_object( $data ): PostModel {
116 - foreach ( $data as $key => $value ) {
117 - if ( property_exists( $this, $key ) ) {
118 - $this->{$key} = $value;
119 - }
120 - }
121 -
122 - return $this;
123 - }
124 -
125 - /**
126 - * Get post course by ID
127 - *
128 - * @param int $post_id
129 - * @param bool $check_cache
130 - *
131 - * @return false|PostModel
132 - * @version 1.0.1
133 - * @since 4.3.2
134 - */
135 - public static function find_by_id( int $post_id, bool $check_cache = false ) {
136 - $filter = new PostFilter();
137 - $filter->ID = $post_id;
138 - $filter->post_type = ( new static() )->post_type;
139 -
140 - $type = ( new static() )->post_type;
141 - $key_cache = "postModel/find/{$post_id}/" . $type;
142 - $lp_cache = new LP_Cache();
143 -
144 - // Check first load cache
145 - $postModel = LP_Cache::cache_load_first( 'get', $key_cache );
146 - if ( false !== $postModel ) {
147 - return $postModel;
148 - }
149 -
150 - // Check cache
151 - if ( $check_cache ) {
152 - $postModel = $lp_cache->get_cache( $key_cache );
153 - if ( $postModel instanceof PostModel ) {
154 - return $postModel;
155 - }
156 - }
157 -
158 - $postModel = self::get_item_model_from_db( $filter );
159 - // Set cache
160 - if ( $postModel instanceof PostModel ) {
161 - $lp_cache->set_cache( $key_cache, $postModel );
162 - }
163 - LP_Cache::cache_load_first( 'set', $key_cache, $postModel );
164 -
165 - return $postModel;
166 - }
167 -
168 - /**
169 - * Get post from database.
170 - * If not exists, return false.
171 - * If exists, return PostModel.
172 - *
173 - * @param LP_Post_Type_Filter|FilterBase $filter
174 - *
175 - * @return PostModel|false|static
176 - * @version 1.0.2
177 - */
178 - public static function get_item_model_from_db( $filter ) {
179 - $lp_post_db = PostDB::getInstance();
180 - $post_model = false;
181 -
182 - try {
183 - if ( empty( $filter->post_type ) ) {
184 - $filter->post_type = ( new static() )->post_type;
185 - }
186 -
187 - $lp_post_db->get_query_single_row( $filter );
188 - $query_single_row = $lp_post_db->get_posts( $filter );
189 - $post_rs = $lp_post_db->wpdb->get_row( $query_single_row );
190 -
191 - if ( $post_rs instanceof stdClass ) {
192 - $post_model = new static( $post_rs );
193 - }
194 - } catch ( Throwable $e ) {
195 - error_log( __METHOD__ . ': ' . $e->getMessage() );
196 - }
197 -
198 - return $post_model;
199 - }
200 -
201 - /**
202 - * Get all meta_data, all keys of a user it
203 - *
204 - * @return stdClass|null
205 - * @throws Exception
206 - * @version 1.0.1
207 - * @since 4.2.6.9
208 - */
209 - public function get_all_metadata() {
210 - if ( ! isset( $this->is_got_meta_data ) ) {
211 - $lp_item_meta_db = LP_Post_Meta_DB::getInstance();
212 - $filter = new LP_Post_Meta_Filter();
213 - $filter->post_id = $this->get_id();
214 - $filter->run_query_count = false;
215 - $filter->limit = - 1;
216 -
217 - $metadata_rs = $lp_item_meta_db->get_post_metas( $filter );
218 - if ( ! $metadata_rs instanceof stdClass ) {
219 - $this->meta_data = new stdClass();
220 - foreach ( $metadata_rs as $value ) {
221 - $this->meta_data->{$value->meta_key} = maybe_unserialize( $value->meta_value );
222 - }
223 - }
224 -
225 - $this->is_got_meta_data = 1;
226 - }
227 -
228 - return $this->meta_data;
229 - }
230 -
231 - /**
232 - * Check capabilities to create new post.
233 - *
234 - * @return bool
235 - * @since 4.2.9.4
236 - * @version 1.0.0
237 - */
238 - public function check_capabilities_create(): bool {
239 - return true;
240 - }
241 -
242 - /**
243 - * Check capabilities to update post.
244 - *
245 - * @return bool
246 - * @since 4.2.9.4
247 - * @version 1.0.0
248 - */
249 - public function check_capabilities_update(): bool {
250 - return true;
251 - }
252 -
253 - /**
254 - * Check capabilities of item's course.
255 - * Check user current can edit it.
256 - *
257 - * @return void
258 - * @throws Exception
259 - * @version 1.0.0
260 - * @since 4.2.9
261 - */
262 - public function check_capabilities_create_item_course() {
263 - $course_item_types = CourseModel::item_types_support();
264 - // Questions not type item of course, it is type item of quiz, but need check here.
265 - $course_item_types[] = LP_QUESTION_CPT;
266 - if ( ! in_array( $this->post_type, $course_item_types, true ) ) {
267 - return;
268 - }
269 -
270 - $user = wp_get_current_user();
271 - if ( ! user_can( $user, 'edit_' . LP_LESSON_CPT . 's' ) ) {
272 - throw new Exception( __( 'You do not have permission to create item.', 'learnpress' ) );
273 - }
274 - }
275 -
276 - /**
277 - * Check capabilities of item's course.
278 - * Check user current can edit it.
279 - *
280 - * @return void
281 - * @throws Exception
282 - * @version 1.0.0
283 - * @since 4.2.9
284 - */
285 - public function check_capabilities_update_item_course() {
286 - $course_item_types = CourseModel::item_types_support();
287 - // Questions not type item of course, it is type item of quiz, but need check here.
288 - $course_item_types[] = LP_QUESTION_CPT;
289 - if ( ! in_array( $this->post_type, $course_item_types, true ) ) {
290 - return;
291 - }
292 -
293 - $user = wp_get_current_user();
294 - if ( ! user_can( $user, 'edit_' . LP_LESSON_CPT, $this->ID ) ) {
295 - throw new Exception( __( 'You do not have permission to edit this item.', 'learnpress' ) );
296 - }
297 - }
298 -
299 - /**
300 - * Update data to database.
301 - *
302 - * If user_item_id is empty, insert new data, else update data.
303 - *
304 - * @throws Exception
305 - * @since 4.2.5
306 - * @version 1.0.4
307 - */
308 - public function save( bool $force_save = false ) {
309 - $data = get_object_vars( $this );
310 -
311 - if ( ! empty( $this->meta_data ) ) {
312 - $data['meta_input'] = [];
313 - foreach ( $this->meta_data as $key_meta => $value_meta ) {
314 - $data['meta_input'][ $key_meta ] = $value_meta;
315 - }
316 - }
317 -
318 - // Check if exists course id.
319 - if ( empty( $this->ID ) ) { // Insert data.
320 - // Check permission
321 - if ( ! $force_save ) {
322 - if ( ! $this->check_capabilities_create() ) {
323 - throw new Exception( __( 'You do not have permission to create item.', 'learnpress' ) );
324 - }
325 -
326 - $this->check_capabilities_create_item_course();
327 - }
328 -
329 - unset( $data['ID'] );
330 - $post_id = wp_insert_post( $data, true );
331 - } else { // Update data.
332 - // Check permission
333 - if ( ! $force_save ) {
334 - if ( ! $this->check_capabilities_update() ) {
335 - throw new Exception( __( 'You do not have permission to edit this item.', 'learnpress' ) );
336 - }
337 -
338 - $this->check_capabilities_update_item_course();
339 - }
340 -
341 - $post_id = wp_update_post( $data, true );
342 - }
343 -
344 - if ( is_wp_error( $post_id ) ) {
345 - throw new Exception( $post_id->get_error_message() );
346 - } else {
347 - $this->ID = $post_id;
348 - }
349 -
350 - $post = get_post( $this->ID );
351 - foreach ( get_object_vars( $post ) as $property => $value ) {
352 - // If property is not exists in PostModel, skip it.
353 - if ( ! property_exists( $this, $property ) ) {
354 - continue;
355 - }
356 - $this->{$property} = $value;
357 - }
358 -
359 - $this->clean_caches();
360 - }
361 -
362 - /**
363 - * Delete row
364 - *
365 - * @throws Exception
366 - * @since 4.3.6
367 - * @version 1.0.0
368 - */
369 - public function delete() {
370 - wp_delete_post( $this->get_id(), true );
371 -
372 - // Clear cache
373 - $this->clean_caches();
374 - }
375 -
376 - /**
377 - * Clean caches.
378 - *
379 - * @return void
380 - */
381 - public function clean_caches() {
382 - // Clear cache.
383 - }
384 -
385 - /**
386 - * @return int
387 - */
388 - public function get_id(): int {
389 - return (int) $this->ID;
390 - }
391 -
392 - /**
393 - * Get image url of post.
394 - *
395 - * @param string|int[] $size
396 - *
397 - * @return string
398 - * @since 4.2.6.9
399 - * @version 1.0.3
400 - */
401 - public function get_image_url( $size = 'post-thumbnail' ): string {
402 - $image_url = '';
403 -
404 - if ( has_post_thumbnail( $this ) ) {
405 - if ( is_string( $size ) ) {
406 - $image_url = get_the_post_thumbnail_url( $this, $size );
407 - } elseif ( is_array( $size ) && count( $size ) === 2 ) {
408 - // Check file crop is existing.
409 - $attachment_id = get_post_thumbnail_id( $this );
410 - $file_path = get_attached_file( $attachment_id );
411 - $file_url = wp_get_attachment_url( $attachment_id );
412 - $upload_dir = wp_upload_dir();
413 - $base_dir = $upload_dir['basedir'];
414 -
415 - // Get file path with size.
416 - $file_path_arr = explode( '.', $file_path );
417 - $file_path_length = count( $file_path_arr );
418 - $extension = end( $file_path_arr );
419 - unset( $file_path_arr[ $file_path_length - 1 ] );
420 - $file_path_join = implode( '.', $file_path_arr );
421 - $file_path_with_size = $file_path_join . '-' . $size[0] . 'x' . $size[1] . '.' . $extension;
422 - if ( file_exists( $file_path_with_size ) ) {
423 - $file_url_arr = explode( '.', $file_url );
424 - $file_url_length = count( $file_url_arr );
425 - $url_extension = end( $file_url_arr );
426 - unset( $file_url_arr[ $file_url_length - 1 ] );
427 - $file_url_join = implode( '.', $file_url_arr );
428 - $image_url = $file_url_join . '-' . $size[0] . 'x' . $size[1] . '.' . $url_extension;
429 - } else {
430 - // Custom crop size for image.
431 - $resized_file = wp_get_image_editor( $file_path );
432 -
433 - if ( ! is_wp_error( $resized_file ) ) {
434 - $resized_file->resize( $size[0], $size[1], true );
435 - $resized_image = $resized_file->save( $file_path_with_size );
436 -
437 - if ( ! is_wp_error( $resized_image ) ) {
438 - // Build the URL for the resized image
439 - $imag_dir = $resized_image['path'];
440 - $imag_dir = str_replace( $base_dir, '', $imag_dir );
441 - $image_url = $upload_dir['baseurl'] . $imag_dir;
442 - }
443 - }
444 - }
445 - }
446 - }
447 -
448 - if ( empty( $image_url ) ) {
449 - $image_url = LearnPress::instance()->image( 'no-image.png' );
450 - }
451 -
452 - return $image_url;
453 - }
454 -
455 - /**
456 - * Get meta value by key.
457 - *
458 - * @param string $key
459 - * @param mixed $default_value
460 - * @param bool $single
461 - *
462 - * @return false|mixed
463 - */
464 - public function get_meta_value_by_key( string $key, $default_value = false, bool $single = true ) {
465 - if ( $this->meta_data instanceof stdClass && isset( $this->meta_data->{$key} ) ) {
466 - return maybe_unserialize( $this->meta_data->{$key} );
467 - }
468 -
469 - $value = get_post_meta( $this->ID, $key, $single );
470 - if ( empty( $value ) ) {
471 - $value = $default_value;
472 - }
473 -
474 - $value = maybe_unserialize( $value );
475 - $this->meta_data->{$key} = $value;
476 -
477 - return $value;
478 - }
479 -
480 - /**
481 - * Get meta value by key.
482 - *
483 - * @param string $key
484 - * @param mixed $value
485 - * @param bool $fore_update
486 - *
487 - * @return void
488 - * @throws Exception
489 - * @since 4.2.6.9
490 - * @version 1.0.3
491 - */
492 - public function save_meta_value_by_key( string $key, $value, bool $fore_update = false ) {
493 - // Check permission
494 - if ( ! $fore_update ) {
495 - if ( ! $this->check_capabilities_update() ) {
496 - throw new Exception( __( 'You do not have permission to edit this item.', 'learnpress' ) );
497 - }
498 - $this->check_capabilities_create_item_course();
499 - }
500 -
501 - $this->meta_data->{$key} = $value;
502 - update_post_meta( $this->ID, $key, $value );
503 - }
504 -
505 - /**
506 - * Get categories of course.
507 - *
508 - * @return array|WP_Term[]
509 - * @version 1.0.1
510 - * @since 4.2.3
511 - */
512 - public function get_categories(): array {
513 - $wpPost = new WP_Post( $this );
514 - $categories = get_the_terms( $wpPost, LP_COURSE_CATEGORY_TAX );
515 - if ( ! $categories || $categories instanceof WP_Error ) {
516 - $categories = array();
517 - }
518 -
519 - return $categories;
520 - }
521 -
522 - /**
523 - * Get tags of course.
524 - *
525 - * @return array|WP_Term[]
526 - * @version 1.0.1
527 - * @since 4.2.7.2
528 - */
529 - public function get_tags(): array {
530 - $wpPost = new WP_Post( $this );
531 - $tags = get_the_terms( $wpPost, LP_COURSE_TAXONOMY_TAG );
532 - if ( ! $tags || $tags instanceof WP_Error ) {
533 - $tags = array();
534 - }
535 -
536 - return $tags;
537 - }
538 -
539 - /**
540 - * Get permalink of post
541 - *
542 - * @return string
543 - */
544 - public function get_permalink(): string {
545 - $permalink = get_permalink( $this );
546 - if ( empty( $permalink ) ) {
547 - $permalink = '';
548 - }
549 -
550 - return $permalink;
551 - }
552 -
553 - /**
554 - * Get the content of WP
555 - *
556 - * @return string
557 - */
558 - public function get_the_content(): string {
559 - $content = get_the_content( null, false, $this );
560 - $content = apply_filters( 'the_content', $content );
561 - $content = str_replace( ']]>', ']]&gt;', $content );
562 -
563 - return $content;
564 - }
565 -
566 - /**
567 - * Get excerpt of WP
568 - *
569 - * @return string
570 - */
571 - public function get_the_excerpt(): string {
572 - $content = get_the_excerpt( $this );
573 -
574 - return $content;
575 - }
576 -
577 - /**
578 - * Get title of course
579 - *
580 - * @return string
581 - */
582 - public function get_the_title(): string {
583 - return get_the_title( $this );
584 - }
585 -
586 - /**
587 - * Get edit link of post
588 - *
589 - * @return string|null
590 - * @since 4.2.7.4
591 - * @version 1.0.1
592 - */
593 - public function get_edit_link() {
594 - return admin_url( "post.php?post=$this->ID&action=edit" );
595 - /**
596 - * Not using get_edit_post_link() because it may not return the correct link in some cases
597 - * get_post_type_object is null.
598 - */
599 - //return get_edit_post_link( $this->get_id() );
600 - }
601 -
602 - /**
603 - * Get i18n status
604 - *
605 - * @return string
606 - */
607 - public function get_status_i18n(): string {
608 - switch ( $this->post_status ) {
609 - case self::STATUS_PUBLISH:
610 - return __( 'Published', 'learnpress' );
611 - case self::STATUS_FEATURE:
612 - return __( 'Scheduled', 'learnpress' );
613 - case self::STATUS_TRASH:
614 - return __( 'Trash', 'learnpress' );
615 - case self::STATUS_DRAFT:
616 - return __( 'Draft', 'learnpress' );
617 - case self::STATUS_PRIVATE:
618 - return __( 'Private', 'learnpress' );
619 - case self::STATUS_PENDING:
620 - return __( 'Pending', 'learnpress' );
621 - case self::STATUS_AUTO_DRAFT:
622 - return __( 'Auto Draft', 'learnpress' );
623 - case self::VISIBILITY_PASSWORD:
624 - return __( 'Protected', 'learnpress' );
625 -
626 - default:
627 - return ucfirst( $this->post_status );
628 - }
629 - }
630 -}
1 +<?php
2 +
3 +/**
4 + * Class Course
5 + * To replace class LP_User_Item
6 + *
7 + * @package LearnPress/Classes
8 + * @version 1.0.8
9 + * @since 4.2.6.9
10 + */
11 +
12 +namespace LearnPress\Models;
13 +
14 +use Exception;
15 +use LearnPress;
16 +use LearnPress\Databases\PostDB;
17 +use LearnPress\Filters\FilterBase;
18 +use LearnPress\Filters\PostFilter;
19 +use LearnPress\Services\CourseService;
20 +use LP_Cache;
21 +use LP_Post_Meta_DB;
22 +use LP_Post_Meta_Filter;
23 +use LP_Post_Type_Filter;
24 +
25 +use stdClass;
26 +use Throwable;
27 +use WP_Error;
28 +use WP_Post;
29 +use WP_Term;
30 +
31 +defined( 'ABSPATH' ) || exit();
32 +
33 +class PostModel {
34 + /**
35 + * Auto increment, Primary key
36 + *
37 + * @var int
38 + */
39 + public $ID = 0;
40 + public $post_author = 0;
41 + public $post_date = null;
42 + public $post_date_gmt = null;
43 + public $post_modified = null;
44 + public $post_modified_gmt = null;
45 + public $post_content = '';
46 + public $post_title = '';
47 + public $post_excerpt = '';
48 + public $post_status = '';
49 + public $post_password = '';
50 + public $post_name = '';
51 + public $post_type = 'post';
52 + public $post_parent = 0;
53 + /**
54 + * @var stdClass all meta data
55 + */
56 + public $meta_data = null;
57 + /**
58 + * @var stdClass all meta data
59 + */
60 + public $is_got_meta_data;
61 + /**
62 + * @var string only for set same property with class WP_Post
63 + */
64 + public $filter;
65 +
66 + const STATUS_PUBLISH = 'publish';
67 + const STATUS_TRASH = 'trash';
68 + const STATUS_DRAFT = 'draft';
69 + const STATUS_PRIVATE = 'private';
70 + const STATUS_PENDING = 'pending';
71 + const STATUS_FEATURE = 'future';
72 + const STATUS_AUTO_DRAFT = 'auto-draft';
73 + const VISIBILITY_PASSWORD = 'password';
74 +
75 + /**
76 + * If data get from database, map to object.
77 + * Else create new object to save data to database.
78 + *
79 + * @param array|object|mixed $data
80 + */
81 + public function __construct( $data = null ) {
82 + if ( $data ) {
83 + $this->map_to_object( $data );
84 + }
85 +
86 + if ( is_null( $this->meta_data ) ) {
87 + $this->meta_data = new stdClass();
88 + }
89 + }
90 +
91 + /**
92 + * Get user model
93 + *
94 + * @return false|UserModel
95 + * @since 4.2.6.9
96 + * @version 1.0.1
97 + */
98 + public function get_author_model() {
99 + if ( ! empty( $this->post_author ) ) {
100 + $author_id = $this->post_author;
101 + } else {
102 + $author_id = get_post_field( 'post_author', $this );
103 + }
104 +
105 + return UserModel::find( $author_id, true );
106 + }
107 +
108 + /**
109 + * Map array, object data to PostModel.
110 + * Use for data get from database.
111 + *
112 + * @param array|object|mixed $data
113 + *
114 + * @return PostModel|static
115 + */
116 + public function map_to_object( $data ): PostModel {
117 + foreach ( $data as $key => $value ) {
118 + if ( property_exists( $this, $key ) ) {
119 + $this->{$key} = $value;
120 + }
121 + }
122 +
123 + return $this;
124 + }
125 +
126 + /**
127 + * Get post course by ID
128 + *
129 + * @param int $post_id
130 + * @param bool $check_cache
131 + *
132 + * @return false|PostModel
133 + * @version 1.0.1
134 + * @since 4.3.2
135 + */
136 + public static function find_by_id( int $post_id, bool $check_cache = false ) {
137 + $filter = new PostFilter();
138 + $filter->ID = $post_id;
139 + $filter->post_type = ( new static() )->post_type;
140 +
141 + $type = ( new static() )->post_type;
142 + $key_cache = "postModel/find/{$post_id}/" . $type;
143 + $lp_cache = new LP_Cache();
144 +
145 + // Check first load cache
146 + $postModel = LP_Cache::cache_load_first( 'get', $key_cache );
147 + if ( false !== $postModel ) {
148 + return $postModel;
149 + }
150 +
151 + // Check cache
152 + if ( $check_cache ) {
153 + $postModel = $lp_cache->get_cache( $key_cache );
154 + if ( $postModel instanceof PostModel ) {
155 + return $postModel;
156 + }
157 + }
158 +
159 + $postModel = self::get_item_model_from_db( $filter );
160 + // Set cache
161 + if ( $postModel instanceof PostModel ) {
162 + $lp_cache->set_cache( $key_cache, $postModel );
163 + }
164 + LP_Cache::cache_load_first( 'set', $key_cache, $postModel );
165 +
166 + return $postModel;
167 + }
168 +
169 + /**
170 + * Get post from database.
171 + * If not exists, return false.
172 + * If exists, return PostModel.
173 + *
174 + * @param LP_Post_Type_Filter|FilterBase $filter
175 + *
176 + * @return PostModel|false|static
177 + * @version 1.0.2
178 + */
179 + public static function get_item_model_from_db( $filter ) {
180 + $lp_post_db = PostDB::getInstance();
181 + $post_model = false;
182 +
183 + try {
184 + if ( empty( $filter->post_type ) ) {
185 + $filter->post_type = ( new static() )->post_type;
186 + }
187 +
188 + $lp_post_db->get_query_single_row( $filter );
189 + $query_single_row = $lp_post_db->get_posts( $filter );
190 + $post_rs = $lp_post_db->wpdb->get_row( $query_single_row );
191 +
192 + if ( $post_rs instanceof stdClass ) {
193 + $post_model = new static( $post_rs );
194 + }
195 + } catch ( Throwable $e ) {
196 + error_log( __METHOD__ . ': ' . $e->getMessage() );
197 + }
198 +
199 + return $post_model;
200 + }
201 +
202 + /**
203 + * Get all meta_data, all keys of a user it
204 + *
205 + * @return stdClass|null
206 + * @throws Exception
207 + * @version 1.0.1
208 + * @since 4.2.6.9
209 + */
210 + public function get_all_metadata() {
211 + if ( ! isset( $this->is_got_meta_data ) ) {
212 + $lp_item_meta_db = LP_Post_Meta_DB::getInstance();
213 + $filter = new LP_Post_Meta_Filter();
214 + $filter->post_id = $this->get_id();
215 + $filter->run_query_count = false;
216 + $filter->limit = - 1;
217 +
218 + $metadata_rs = $lp_item_meta_db->get_post_metas( $filter );
219 + if ( ! $metadata_rs instanceof stdClass ) {
220 + $this->meta_data = new stdClass();
221 + foreach ( $metadata_rs as $value ) {
222 + $this->meta_data->{$value->meta_key} = maybe_unserialize( $value->meta_value );
223 + }
224 + }
225 +
226 + $this->is_got_meta_data = 1;
227 + }
228 +
229 + return $this->meta_data;
230 + }
231 +
232 + /**
233 + * Check capabilities to create new post.
234 + *
235 + * @return bool
236 + * @since 4.2.9.4
237 + * @version 1.0.1
238 + */
239 + public function check_capabilities_create(): bool {
240 + //return current_user_can( 'edit_' . $this->post_type . 's' );
241 + return true;
242 + }
243 +
244 + /**
245 + * Check capabilities to update post.
246 + *
247 + * @return bool
248 + * @since 4.2.9.4
249 + * @version 1.0.1
250 + */
251 + public function check_capabilities_update(): bool {
252 + //return current_user_can( 'edit_' . $this->post_type, $this->ID );
253 + return true;
254 + }
255 +
256 + /**
257 + * Check capabilities of item's course.
258 + * Check user current can edit it.
259 + *
260 + * @return void
261 + * @throws Exception
262 + * @version 1.0.1
263 + * @since 4.2.9
264 + */
265 + public function check_capabilities_create_item_course() {
266 + $user = wp_get_current_user();
267 + if ( ! user_can( $user, 'edit_' . LP_LESSON_CPT . 's' ) ) {
268 + throw new Exception( __( 'You do not have permission to create item.', 'learnpress' ) );
269 + }
270 + }
271 +
272 + /**
273 + * Check capabilities of item's course.
274 + * Check user current can edit it.
275 + *
276 + * @return void
277 + * @throws Exception
278 + * @version 1.0.1
279 + * @since 4.2.9
280 + */
281 + public function check_capabilities_update_item_course() {
282 + $user = wp_get_current_user();
283 + if ( ! user_can( $user, 'edit_' . LP_LESSON_CPT, $this->ID ) ) {
284 + throw new Exception( __( 'You do not have permission to edit this item.', 'learnpress' ) );
285 + }
286 + }
287 +
288 + /**
289 + * Update data to database.
290 + *
291 + * If user_item_id is empty, insert new data, else update data.
292 + *
293 + * @throws Exception
294 + * @since 4.2.5
295 + * @version 1.0.5
296 + */
297 + public function save( bool $force_save = false ) {
298 + $data = get_object_vars( $this );
299 +
300 + if ( ! empty( $this->meta_data ) ) {
301 + $data['meta_input'] = [];
302 + foreach ( $this->meta_data as $key_meta => $value_meta ) {
303 + $data['meta_input'][ $key_meta ] = $value_meta;
304 + }
305 + }
306 +
307 + // Check if exists course id.
308 + if ( empty( $this->ID ) ) { // Insert data.
309 + // Check permission
310 + if ( ! $force_save ) {
311 + if ( CourseService::check_is_item_type_of_course( $this->post_type )
312 + || LP_QUESTION_CPT === $this->post_type ) {
313 + $this->check_capabilities_create_item_course();
314 + } elseif ( ! $this->check_capabilities_create() ) {
315 + throw new Exception( __( 'You do not have permission to create item.', 'learnpress' ) );
316 + }
317 + }
318 +
319 + unset( $data['ID'] );
320 + $post_id = wp_insert_post( $data, true );
321 + } else { // Update data.
322 + // Check permission
323 + if ( ! $force_save ) {
324 + if ( courseservice::check_is_item_type_of_course( $this->post_type )
325 + || LP_QUESTION_CPT === $this->post_type ) {
326 + $this->check_capabilities_update_item_course();
327 + } elseif ( ! $this->check_capabilities_update() ) {
328 + throw new exception( __( 'you do not have permission to edit this item.', 'learnpress' ) );
329 + }
330 + }
331 +
332 + $post_id = wp_update_post( $data, true );
333 + }
334 +
335 + if ( is_wp_error( $post_id ) ) {
336 + throw new Exception( $post_id->get_error_message() );
337 + } else {
338 + $this->ID = $post_id;
339 + }
340 +
341 + $post = get_post( $this->ID );
342 + foreach ( get_object_vars( $post ) as $property => $value ) {
343 + // If property is not exists in PostModel, skip it.
344 + if ( ! property_exists( $this, $property ) ) {
345 + continue;
346 + }
347 + $this->{$property} = $value;
348 + }
349 +
350 + $this->clean_caches();
351 + }
352 +
353 + /**
354 + * Delete row
355 + *
356 + * @throws Exception
357 + * @since 4.3.6
358 + * @version 1.0.0
359 + */
360 + public function delete() {
361 + wp_delete_post( $this->get_id(), true );
362 +
363 + // Clear cache
364 + $this->clean_caches();
365 + }
366 +
367 + /**
368 + * Clean caches.
369 + *
370 + * @return void
371 + */
372 + public function clean_caches() {
373 + // Clear cache.
374 + }
375 +
376 + /**
377 + * @return int
378 + */
379 + public function get_id(): int {
380 + return (int) $this->ID;
381 + }
382 +
383 + /**
384 + * Get image url of post.
385 + *
386 + * @param string|int[] $size
387 + *
388 + * @return string
389 + * @since 4.2.6.9
390 + * @version 1.0.3
391 + */
392 + public function get_image_url( $size = 'post-thumbnail' ): string {
393 + $image_url = '';
394 +
395 + if ( has_post_thumbnail( $this ) ) {
396 + if ( is_string( $size ) ) {
397 + $image_url = get_the_post_thumbnail_url( $this, $size );
398 + } elseif ( is_array( $size ) && count( $size ) === 2 ) {
399 + // Check file crop is existing.
400 + $attachment_id = get_post_thumbnail_id( $this );
401 + $file_path = get_attached_file( $attachment_id );
402 + $file_url = wp_get_attachment_url( $attachment_id );
403 + $upload_dir = wp_upload_dir();
404 + $base_dir = $upload_dir['basedir'];
405 +
406 + // Get file path with size.
407 + $file_path_arr = explode( '.', $file_path );
408 + $file_path_length = count( $file_path_arr );
409 + $extension = end( $file_path_arr );
410 + unset( $file_path_arr[ $file_path_length - 1 ] );
411 + $file_path_join = implode( '.', $file_path_arr );
412 + $file_path_with_size = $file_path_join . '-' . $size[0] . 'x' . $size[1] . '.' . $extension;
413 + if ( file_exists( $file_path_with_size ) ) {
414 + $file_url_arr = explode( '.', $file_url );
415 + $file_url_length = count( $file_url_arr );
416 + $url_extension = end( $file_url_arr );
417 + unset( $file_url_arr[ $file_url_length - 1 ] );
418 + $file_url_join = implode( '.', $file_url_arr );
419 + $image_url = $file_url_join . '-' . $size[0] . 'x' . $size[1] . '.' . $url_extension;
420 + } else {
421 + // Custom crop size for image.
422 + $resized_file = wp_get_image_editor( $file_path );
423 +
424 + if ( ! is_wp_error( $resized_file ) ) {
425 + $resized_file->resize( $size[0], $size[1], true );
426 + $resized_image = $resized_file->save( $file_path_with_size );
427 +
428 + if ( ! is_wp_error( $resized_image ) ) {
429 + // Build the URL for the resized image
430 + $imag_dir = $resized_image['path'];
431 + $imag_dir = str_replace( $base_dir, '', $imag_dir );
432 + $image_url = $upload_dir['baseurl'] . $imag_dir;
433 + }
434 + }
435 + }
436 + }
437 + }
438 +
439 + if ( empty( $image_url ) ) {
440 + $image_url = LearnPress::instance()->image( 'no-image.png' );
441 + }
442 +
443 + return $image_url;
444 + }
445 +
446 + /**
447 + * Get meta value by key.
448 + *
449 + * @param string $key
450 + * @param mixed $default_value
451 + * @param bool $single
452 + *
453 + * @return false|mixed
454 + */
455 + public function get_meta_value_by_key( string $key, $default_value = false, bool $single = true ) {
456 + if ( $this->meta_data instanceof stdClass && isset( $this->meta_data->{$key} ) ) {
457 + return maybe_unserialize( $this->meta_data->{$key} );
458 + }
459 +
460 + $value = get_post_meta( $this->ID, $key, $single );
461 + if ( empty( $value ) ) {
462 + $value = $default_value;
463 + }
464 +
465 + $value = maybe_unserialize( $value );
466 + $this->meta_data->{$key} = $value;
467 +
468 + return $value;
469 + }
470 +
471 + /**
472 + * Get meta value by key.
473 + *
474 + * @param string $key
475 + * @param mixed $value
476 + * @param bool $fore_update
477 + *
478 + * @return void
479 + * @throws Exception
480 + * @since 4.2.6.9
481 + * @version 1.0.3
482 + */
483 + public function save_meta_value_by_key( string $key, $value, bool $fore_update = false ) {
484 + // Check permission
485 + if ( ! $fore_update ) {
486 + if ( ! $this->check_capabilities_update() ) {
487 + throw new Exception( __( 'You do not have permission to edit this item.', 'learnpress' ) );
488 + }
489 + $this->check_capabilities_create_item_course();
490 + }
491 +
492 + $this->meta_data->{$key} = $value;
493 + update_post_meta( $this->ID, $key, $value );
494 + }
495 +
496 + /**
497 + * Get categories of course.
498 + *
499 + * @return array|WP_Term[]
500 + * @version 1.0.1
501 + * @since 4.2.3
502 + */
503 + public function get_categories(): array {
504 + $wpPost = new WP_Post( $this );
505 + $categories = get_the_terms( $wpPost, LP_COURSE_CATEGORY_TAX );
506 + if ( ! $categories || $categories instanceof WP_Error ) {
507 + $categories = array();
508 + }
509 +
510 + return $categories;
511 + }
512 +
513 + /**
514 + * Get tags of course.
515 + *
516 + * @return array|WP_Term[]
517 + * @version 1.0.1
518 + * @since 4.2.7.2
519 + */
520 + public function get_tags(): array {
521 + $wpPost = new WP_Post( $this );
522 + $tags = get_the_terms( $wpPost, LP_COURSE_TAXONOMY_TAG );
523 + if ( ! $tags || $tags instanceof WP_Error ) {
524 + $tags = array();
525 + }
526 +
527 + return $tags;
528 + }
529 +
530 + /**
531 + * Get permalink of post
532 + *
533 + * @return string
534 + */
535 + public function get_permalink(): string {
536 + $permalink = get_permalink( $this );
537 + if ( empty( $permalink ) ) {
538 + $permalink = '';
539 + }
540 +
541 + return $permalink;
542 + }
543 +
544 + /**
545 + * Get the content of WP
546 + *
547 + * @return string
548 + */
549 + public function get_the_content(): string {
550 + $content = get_the_content( null, false, $this );
551 + $content = apply_filters( 'the_content', $content );
552 + $content = str_replace( ']]>', ']]&gt;', $content );
553 +
554 + return $content;
555 + }
556 +
557 + /**
558 + * Get excerpt of WP
559 + *
560 + * @return string
561 + */
562 + public function get_the_excerpt(): string {
563 + $content = get_the_excerpt( $this );
564 +
565 + return $content;
566 + }
567 +
568 + /**
569 + * Get title of course
570 + *
571 + * @return string
572 + */
573 + public function get_the_title(): string {
574 + return get_the_title( $this );
575 + }
576 +
577 + /**
578 + * Get edit link of post
579 + *
580 + * @return string|null
581 + * @since 4.2.7.4
582 + * @version 1.0.1
583 + */
584 + public function get_edit_link() {
585 + return admin_url( "post.php?post=$this->ID&action=edit" );
586 + /**
587 + * Not using get_edit_post_link() because it may not return the correct link in some cases
588 + * get_post_type_object is null.
589 + */
590 + //return get_edit_post_link( $this->get_id() );
591 + }
592 +
593 + /**
594 + * Get i18n status
595 + *
596 + * @return string
597 + */
598 + public function get_status_i18n(): string {
599 + switch ( $this->post_status ) {
600 + case self::STATUS_PUBLISH:
601 + return __( 'Published', 'learnpress' );
602 + case self::STATUS_FEATURE:
603 + return __( 'Scheduled', 'learnpress' );
604 + case self::STATUS_TRASH:
605 + return __( 'Trash', 'learnpress' );
606 + case self::STATUS_DRAFT:
607 + return __( 'Draft', 'learnpress' );
608 + case self::STATUS_PRIVATE:
609 + return __( 'Private', 'learnpress' );
610 + case self::STATUS_PENDING:
611 + return __( 'Pending', 'learnpress' );
612 + case self::STATUS_AUTO_DRAFT:
613 + return __( 'Auto Draft', 'learnpress' );
614 + case self::VISIBILITY_PASSWORD:
615 + return __( 'Protected', 'learnpress' );
616 +
617 + default:
618 + return ucfirst( $this->post_status );
619 + }
620 + }
621 +}