LearnPress – WordPress LMS Plugin - Version 4.0.7-beta-1

Version Description

= 4.0.0 = In this version, we have to change the database structure, so that if you have installed LP3 on your site before, please backup your site and follow these steps to upgrade.

= 0.9.19 = In this version, we have changed a little bit about LearnPress Plugin directory structure and moved all add-ons to become independent plugins. If you face any problems related to add-ons, please completely remove old version and re-install LearnPress. It does not affect your current data. Thank you.

Download this release

Release Info

Developer ThimPress
Plugin Icon 128x128 LearnPress – WordPress LMS Plugin
Version 4.0.7-beta-1
Comparing to
See all releases

Code changes from version 4.0.6 to 4.0.7-beta-1

inc/background-process/class-lp-background-clear-temp-users.php DELETED
@@ -1,62 +0,0 @@
1
- <?php
2
- defined( 'ABSPATH' ) || exit;
3
-
4
- if ( ! class_exists( 'LP_Background_Clear_Temp_Users' ) ) {
5
- /**
6
- * Class LP_Background_Clear_Temp_Users
7
- *
8
- * @since 3.0.0
9
- */
10
- class LP_Background_Clear_Temp_Users extends LP_Abstract_Background_Process {
11
-
12
- /**
13
- * @var int
14
- */
15
- protected $queue_lock_time = 60;
16
-
17
- /**
18
- * @var string
19
- */
20
- protected $action = 'lp_clear_temp_users';
21
-
22
- /**
23
- * @var string
24
- */
25
- protected $transient_key = 'lp_schedule_clear_temp_users';
26
-
27
-
28
- /**
29
- * LP_Background_Clear_Temp_Users constructor.
30
- */
31
- public function __construct() {
32
- parent::__construct();
33
- }
34
-
35
- /**
36
- * @param mixed $data
37
- *
38
- * @return bool
39
- */
40
- protected function task( $data ) {
41
- global $wpdb;
42
-
43
- parent::task( $data );
44
-
45
- if ( ! empty( $data['action'] ) && 'clear_temp_users' == $data['action'] ) {
46
- $query = $wpdb->prepare(
47
- "
48
- DELETE a.*, b.*
49
- FROM {$wpdb->prefix}learnpress_user_items a
50
- INNER JOIN {$wpdb->prefix}learnpress_user_itemmeta b
51
- WHERE a.user_item_id = b.learnpress_user_item_id
52
- AND a.user_id = %d
53
- ",
54
- $data['users']
55
- );
56
- $wpdb->query( $query );
57
- }
58
-
59
- return false;
60
- }
61
- }
62
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/background-process/class-lp-background-emailer.php CHANGED
@@ -4,13 +4,13 @@
4
  */
5
  defined( 'ABSPATH' ) || exit;
6
 
7
- if ( ! class_exists( 'LP_Background_Emailer' ) ) {
8
  /**
9
  * Class LP_Background_Emailer
10
  *
11
  * @since 3.0.0
12
  */
13
- class LP_Background_Emailer extends LP_Abstract_Background_Process {
14
 
15
  /**
16
  * @var string
@@ -49,5 +49,3 @@ if ( ! class_exists( 'LP_Background_Emailer' ) ) {
49
  }
50
  }
51
  }
52
-
53
- return LP_Background_Emailer::instance();
4
  */
5
  defined( 'ABSPATH' ) || exit;
6
 
7
+ if ( ! class_exists( 'LP_Background_Email' ) ) {
8
  /**
9
  * Class LP_Background_Emailer
10
  *
11
  * @since 3.0.0
12
  */
13
+ class LP_Background_Email extends LP_Abstract_Background_Process {
14
 
15
  /**
16
  * @var string
49
  }
50
  }
51
  }
 
 
inc/background-process/class-lp-background-global.php DELETED
@@ -1,75 +0,0 @@
1
- <?php
2
- /**
3
- * Send emails in background
4
- */
5
- defined( 'ABSPATH' ) || exit;
6
-
7
- if ( ! class_exists( 'LP_Background_Global' ) ) {
8
- /**
9
- * Class LP_Background_Global
10
- *
11
- * @since 3.0.0
12
- */
13
- class LP_Background_Global extends LP_Abstract_Background_Process {
14
-
15
- /**
16
- * @var string
17
- */
18
- protected $action = 'lp_background';
19
-
20
- /**
21
- * @var int
22
- */
23
- protected $queue_lock_time = 60;
24
-
25
- /**
26
- * LP_Background_Global constructor.
27
- */
28
- public function __construct() {
29
- parent::__construct();
30
- }
31
-
32
- /**
33
- * @param string $action
34
- * @param array $args
35
- * @param string $callback
36
- */
37
- public static function add( $action, $args = array(), $callback = '' ) {
38
- $item = array(
39
- 'action' => $action,
40
- 'callback' => $callback,
41
- 'args' => $args,
42
- );
43
-
44
- $instance = self::instance();
45
- $instance->push_to_queue( $item );
46
- }
47
-
48
- /**
49
- * @param mixed $callback
50
- *
51
- * @return bool
52
- */
53
- protected function task( $callback ) {
54
- parent::task( $callback );
55
-
56
- if ( isset( $callback['action'] ) ) {
57
- $args = isset( $callback['args'] ) ? $callback['args'] : array();
58
- try {
59
-
60
- if ( is_callable( $callback['callback'] ) ) {
61
- call_user_func( $callback['callback'], $callback );
62
- }
63
-
64
- do_action( 'learn-press/background/' . $callback['action'], $callback );
65
- } catch ( Exception $e ) {
66
-
67
- }
68
- }
69
-
70
- return false;
71
- }
72
- }
73
- }
74
-
75
- return LP_Background_Global::instance();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/background-process/class-lp-background-installer.php CHANGED
@@ -1,4 +1,10 @@
1
  <?php
 
 
 
 
 
 
2
  defined( 'ABSPATH' ) || exit;
3
 
4
  if ( ! class_exists( 'LP_Background_Installer' ) ) {
@@ -7,55 +13,12 @@ if ( ! class_exists( 'LP_Background_Installer' ) ) {
7
  *
8
  * @since 3.0.0
9
  */
10
- class LP_Background_Installer extends LP_Abstract_Background_Process {
11
-
12
- /**
13
- * @var int
14
- */
15
-
16
- /**
17
- * @var string
18
- */
19
- protected $action = 'lp_installer';
20
 
21
  /**
22
  * LP_Background_Installer constructor.
23
  */
24
  public function __construct() {
25
- parent::__construct();
26
-
27
- if ( 'yes' !== get_option( 'learn_press_check_tables' ) ) {
28
- add_action( 'wp_loaded', array( $this, 'check' ), 100 );
29
- }
30
- }
31
-
32
- public function check() {
33
- $this->push_to_queue(
34
- array(
35
- 'check_tables' => 'yes',
36
- )
37
- )->save()->dispatch();
38
- }
39
-
40
- /**
41
- * @param mixed $data
42
- *
43
- * @return bool
44
- */
45
- protected function task( $data ) {
46
- parent::task( $data );
47
-
48
- if ( ! isset( $data['check_tables'] ) ) {
49
- return false;
50
- }
51
-
52
- LP_Install::create_tables();
53
-
54
- if ( ! $this->get_missing_tables() ) {
55
- update_option( 'learn_press_check_tables', 'yes', 'yes' );
56
- }
57
-
58
- return false;
59
  }
60
 
61
  /**
@@ -63,45 +26,17 @@ if ( ! class_exists( 'LP_Background_Installer' ) ) {
63
  *
64
  * @return array
65
  */
66
- protected function get_missing_tables() {
67
- global $wpdb;
68
- $query = $wpdb->prepare(
69
- '
70
- SHOW TABLES LIKE %s
71
- ',
72
- '%' . $wpdb->esc_like( 'learnpress' ) . '%'
73
- );
74
-
75
- $tables = $wpdb->get_col( $query );
76
-
77
- $required_tables = get_object_vars( $wpdb );
78
- $required_tables = array_filter( $required_tables, array( $this, '_filter_tables' ) );
79
-
80
- return array_diff( $required_tables, $tables );
81
  }
82
 
83
  /**
84
- * Filter callback to get all tables of LP assigned to $wpdb.
85
  *
86
- * @version 3.2.2
87
- *
88
- * @param string $prop
89
- *
90
- * @return bool
91
  */
92
- protected function _filter_tables( $prop ) {
93
- global $wpdb;
94
 
95
- return is_string( $prop ) && strpos( $prop, $wpdb->prefix . 'learnpress' ) === 0;
96
- }
97
-
98
- /**
99
- * @return LP_Background_Installer
100
- */
101
- public static function instance() {
102
- return parent::instance();
103
  }
104
  }
105
  }
106
-
107
- return LP_Background_Installer::instance();
1
  <?php
2
+ /**
3
+ * class LP_Background_Installer
4
+ *
5
+ * @since 4.0.7
6
+ * @author tungnx
7
+ */
8
  defined( 'ABSPATH' ) || exit;
9
 
10
  if ( ! class_exists( 'LP_Background_Installer' ) ) {
13
  *
14
  * @since 3.0.0
15
  */
16
+ class LP_Background_Installer {
 
 
 
 
 
 
 
 
 
17
 
18
  /**
19
  * LP_Background_Installer constructor.
20
  */
21
  public function __construct() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  }
23
 
24
  /**
26
  *
27
  * @return array
28
  */
29
+ protected function get_tables_missing() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
  }
31
 
32
  /**
33
+ * Get tables must have on this version of LP
34
  *
35
+ * @since 4.0.7
36
+ * @author tungnx
 
 
 
37
  */
38
+ protected function get_tables_require() {
 
39
 
 
 
 
 
 
 
 
 
40
  }
41
  }
42
  }
 
 
inc/background-process/class-lp-background-query-items.php CHANGED
@@ -19,6 +19,8 @@ if ( ! class_exists( 'LP_Background_Query_Items' ) ) {
19
  */
20
  protected $queue_lock_time = 3600;
21
 
 
 
22
  /**
23
  * @var float|int
24
  */
19
  */
20
  protected $queue_lock_time = 3600;
21
 
22
+ protected $cron_interval = 60 * 24; // minutes
23
+
24
  /**
25
  * @var float|int
26
  */
inc/background-process/class-lp-background-schedule-items.php DELETED
@@ -1,257 +0,0 @@
1
- <?php
2
- defined( 'ABSPATH' ) || exit;
3
-
4
- if ( ! class_exists( 'LP_Background_Schedule_Items' ) ) {
5
- /**
6
- * Class LP_Background_Schedule_Items
7
- *
8
- * @since 3.0.0
9
- */
10
- class LP_Background_Schedule_Items extends LP_Abstract_Background_Process {
11
-
12
- /**
13
- * @var int
14
- */
15
- protected $queue_lock_time = 60;
16
-
17
- /**
18
- * @var string
19
- */
20
- protected $action = 'schedule_items';
21
-
22
- /**
23
- * @var string
24
- */
25
- protected $transient_key = 'lp_schedule_complete_items';
26
-
27
-
28
- /**
29
- * LP_Background_Schedule_Items constructor.
30
- */
31
- public function __construct() {
32
- parent::__construct();
33
-
34
- add_action( 'learn_press_schedule_items', array( $this, 'xxx' ) );
35
-
36
- }
37
-
38
- public function xxx() {
39
- $this->run();
40
-
41
- $t = date( 'H.i.s' );
42
- sleep( 15 );
43
- }
44
-
45
- public function cron_schedules( $schedules ) {
46
- $schedules['lp_cron_schedule'] = array(
47
- 'interval' => 15,
48
- 'display' => __( 'Every 3 Minutes', 'learnpress' ),
49
- );
50
-
51
- return $schedules;
52
- }
53
-
54
- /**
55
- * Run
56
- */
57
- public function run() {
58
- if ( ! $this->has_queued() ) {
59
- $this->push_to_queue(
60
- array( 'x' => 100 )
61
- )->save()->dispatch();
62
- } else {
63
- $this->dispatch();
64
- }
65
- }
66
-
67
- /**
68
- * Update user-item status.
69
- * This function called in background by schedule event.
70
- *
71
- * @param mixed $data
72
- *
73
- * @editor tungnx
74
- * @reason not use
75
- *
76
- * @return bool
77
- * @since 3.3.0
78
- *
79
- */
80
- /*protected function task( $data ) {
81
-
82
- $settings = LP_Settings::instance();
83
-
84
- // If option auto finish course is turn off.
85
- if ( 'yes' !== $settings->get( 'auto_finish_course', 'yes' ) ) {
86
- die();
87
- }
88
-
89
- $curd = new LP_User_CURD();
90
-
91
- // Get all courses in user-items are in-progress but has expired
92
- $course_items = $curd->get_courses(
93
- array(
94
- 'status' => 'in-progress',
95
- 'expired' => true,
96
- 'paginate' => false,
97
- 'no_join_users' => true,
98
- 'limit' => 100,
99
- )
100
- );
101
-
102
- if ( ! $course_items ) {
103
- die();
104
- }
105
-
106
- // Force auto completing course items if turn on.
107
- $complete_items = 'yes' === $settings->get( 'force_complete_course_items', 'yes' );
108
-
109
- // Cron-job auto finish course when expiration time (nhamdv).
110
- foreach ( $course_items as $course_item ) {
111
- $user = learn_press_get_user( $course_item->user_id );
112
- $course_data = $user->get_course_data( $course_item->course_id );
113
-
114
- $finished = $course_data->finish( $complete_items );
115
-
116
- learn_press_update_user_item_meta( $finished, 'finishing_type', 'exceeded' );
117
- }
118
-
119
- return false;
120
- }*/
121
-
122
- /**
123
- * Get the items.
124
- *
125
- * @return array|bool
126
- */
127
- protected function _get_items() {
128
- global $wpdb;
129
- $queued_items = get_transient( $this->transient_key );
130
- $queued_course_ids = $queued_items ? array_keys( $queued_items ) : false;
131
- $queued_course_ids = array_unique( $queued_course_ids );
132
- $exclude_items = $queued_course_ids ? 'AND user_item_id NOT IN(' . join( ',',
133
- $queued_course_ids ) . ')' : '';
134
-
135
- $null_time = '0000-00-00 00:00:00';
136
- $query = $wpdb->prepare(
137
- "
138
- SELECT user_item_id, user_id
139
- FROM {$wpdb->learnpress_user_items}
140
- WHERE item_type = %s
141
- AND ( end_time IS NULL OR end_time = %s OR status <> %s )
142
- {$exclude_items}
143
- LIMIT 0, 1
144
- ",
145
- LP_COURSE_CPT,
146
- $null_time,
147
- 'finished'
148
- );
149
-
150
- $item_courses = $wpdb->get_results( $query );
151
-
152
- if ( ! $item_courses ) {
153
- return false;
154
- }
155
-
156
- if ( ! $queued_items ) {
157
- $queued_items = array();
158
- }
159
-
160
- $course_item_types = learn_press_get_course_item_types();
161
- $format = array_fill( 0, sizeof( $course_item_types ), '%s' );
162
- $args = $course_item_types;
163
- $new_items = array();
164
-
165
- die();
166
-
167
- foreach ( $item_courses as $item_course ) {
168
- $new_items[ $item_course->user_item_id ] = array();
169
-
170
- $args['end_time'] = $null_time;
171
- $args['status'] = 'completed';
172
- $args['parent'] = $item_course->user_item_id;
173
- $query = $wpdb->prepare(
174
- "
175
- SELECT user_item_id
176
- FROM {$wpdb->learnpress_user_items}
177
- WHERE item_type IN(" . join( ',', $format ) . ')
178
- AND ( end_time IS NULL OR end_time = %s OR status <> %s )
179
- AND parent_id = %d
180
- ',
181
- $args
182
- );
183
-
184
- $item_course_items = $wpdb->get_col( $query );
185
- if ( $item_course_items ) {
186
- $new_items[ $item_course->user_item_id ] = $item_course_items;
187
- }
188
- }
189
-
190
- foreach ( $new_items as $user_item_id => $items ) {
191
- if ( array_key_exists( $user_item_id, $queued_items ) ) {
192
- $queued_items[ $user_item_id ] = array_merge( $queued_items[ $user_item_id ], $items );
193
- } else {
194
- $queued_items[ $user_item_id ] = $items;
195
- }
196
- }
197
-
198
- set_transient( $this->transient_key, $queued_items );
199
-
200
- return $new_items;
201
- }
202
-
203
- /**
204
- * @param array $item
205
- */
206
- protected function finish_course( $item ) {
207
-
208
- $item_course = new LP_User_Item_Course( $item );
209
- if ( ! $item_course ) {
210
- return;
211
- }
212
-
213
- $user = $item_course->get_user();
214
- if ( ! $user ) {
215
- return;
216
- }
217
-
218
- }
219
-
220
- /**
221
- * @param array $item
222
- */
223
- protected function complete_lesson( $item ) {
224
- $item_course = new LP_User_Item_Course( $item );
225
-
226
- if ( ! $item_course ) {
227
- return;
228
- }
229
-
230
- $user = $item_course->get_user();
231
-
232
- if ( $user ) {
233
- return;
234
- }
235
-
236
- $user->finish_course( $item_course->get_item_id() );
237
- }
238
-
239
- /**
240
- * Schedule fallback event.
241
- */
242
- protected function schedule_event() {
243
- if ( ! wp_next_scheduled( $this->cron_hook_identifier ) ) {
244
- wp_schedule_event( time() + 10, $this->cron_interval_identifier, $this->cron_hook_identifier );
245
- }
246
- }
247
-
248
- /**
249
- * @return LP_Background_Schedule_Items
250
- */
251
- public static function instance() {
252
- return parent::instance();
253
- }
254
- }
255
- }
256
-
257
- return LP_Background_Schedule_Items::instance();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/background-process/class-lp-background-sync-data.php DELETED
@@ -1,68 +0,0 @@
1
- <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- exit;
4
- }
5
-
6
- if ( ! class_exists( 'LP_Background_Sync_Data' ) ) {
7
- /**
8
- * Class LP_Background_Sync_Data
9
- *
10
- * @since 3.0.0
11
- */
12
- class LP_Background_Sync_Data extends LP_Abstract_Background_Process {
13
-
14
- /**
15
- * @var int
16
- */
17
- protected $queue_lock_time = 60;
18
-
19
- /**
20
- * @var string
21
- */
22
- protected $action = 'lp_sync_data';
23
-
24
- /**
25
- * @var string
26
- */
27
- protected $transient_key = 'lp_schedule_complete_items';
28
-
29
-
30
- /**
31
- * LP_Background_Sync_Data constructor.
32
- */
33
- public function __construct() {
34
- parent::__construct();
35
- }
36
-
37
- public function test() {
38
- $this->task( 0 );
39
- }
40
-
41
- /**
42
- * @param mixed $data
43
- *
44
- * @return bool
45
- */
46
- protected function task( $data ) {
47
- $queue_user_ids = get_option( $data['option_key'] );
48
-
49
- if ( ! $queue_user_ids ) {
50
- delete_option( $data['option_key'] );
51
- delete_option( 'doing-sync-user-course-results' );
52
-
53
- return false;
54
- } else {
55
- update_option( $data['option_key'], $queue_user_ids, 'no' );
56
- }
57
-
58
- return $data;
59
- }
60
-
61
- public function is_running() {
62
- return false === $this->is_queue_empty();
63
- }
64
-
65
- }
66
- }
67
-
68
- return LP_Background_Sync_Data::instance();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
inc/class-lp-emails.php CHANGED
@@ -182,18 +182,22 @@ if ( ! class_exists( 'LP_Emails' ) ) {
182
  )
183
  );
184
 
185
- if ( 'yes' === LP()->settings()->get( 'emails_general.send_email_background' ) ) {
 
186
 
187
  // self::$_background_emailer = new LP_Background_Emailer();
188
 
189
  foreach ( $actions as $action ) {
190
- add_action( $action, array( __CLASS__, 'queue_email' ), 10, 10 );
191
  }
192
  } else {
193
-
194
  foreach ( $actions as $action ) {
195
  add_action( $action, array( __CLASS__, 'send_email' ), 10, 10 );
196
  }
 
 
 
 
197
  }
198
 
199
  self::instance();
@@ -204,13 +208,13 @@ if ( ! class_exists( 'LP_Emails' ) ) {
204
  *
205
  * @since 3.0.0
206
  */
207
- public static function queue_email() {
208
  $data_queue = array(
209
  'filter' => current_filter(),
210
  'args' => func_get_args(),
211
  );
212
  LP()->background( 'emailer' )->push_to_queue( $data_queue );
213
- }
214
 
215
  /**
216
  * Send email notification.
182
  )
183
  );
184
 
185
+ //TODO: tungnx - rewrite background progess
186
+ /*if ( 'yes' === LP()->settings()->get( 'emails_general.send_email_background' ) ) {
187
 
188
  // self::$_background_emailer = new LP_Background_Emailer();
189
 
190
  foreach ( $actions as $action ) {
191
+ //add_action( $action, array( __CLASS__, 'queue_email' ), 10, 10 );
192
  }
193
  } else {
 
194
  foreach ( $actions as $action ) {
195
  add_action( $action, array( __CLASS__, 'send_email' ), 10, 10 );
196
  }
197
+ }*/
198
+
199
+ foreach ( $actions as $action ) {
200
+ add_action( $action, array( __CLASS__, 'send_email' ), 10, 10 );
201
  }
202
 
203
  self::instance();
208
  *
209
  * @since 3.0.0
210
  */
211
+ /*public static function queue_email() {
212
  $data_queue = array(
213
  'filter' => current_filter(),
214
  'args' => func_get_args(),
215
  );
216
  LP()->background( 'emailer' )->push_to_queue( $data_queue );
217
+ }*/
218
 
219
  /**
220
  * Send email notification.
inc/class-lp-repair-database.php CHANGED
@@ -607,10 +607,11 @@ class LP_Repair_Database {
607
  * Sync course data when saving post.
608
  *
609
  * @param int $course_id
610
- *
 
611
  * @since 3.1.0
612
  */
613
- public function sync_course_data( $course_id ) {
614
  $user_curd = new LP_User_CURD();
615
  $course_curd = new LP_Course_CURD();
616
 
@@ -621,8 +622,6 @@ class LP_Repair_Database {
621
  }
622
 
623
  update_post_meta( $course_id, 'count_items', $count_items );
624
- $this->queue_sync_user_course_results( $course_id );
625
-
626
  }
627
 
628
  /**
@@ -648,7 +647,12 @@ class LP_Repair_Database {
648
  call_user_func( array( $this, $func ) );
649
  }
650
 
651
- public function queue_sync_user_course_results( $course_id ) {
 
 
 
 
 
652
  global $wpdb;
653
  $query = $wpdb->prepare(
654
  "
@@ -693,7 +697,7 @@ class LP_Repair_Database {
693
  update_option( 'doing-sync-user-course-results', 'yes' );
694
  }
695
  }
696
- }
697
 
698
  /**
699
  * Sync orders for each course
607
  * Sync course data when saving post.
608
  *
609
  * @param int $course_id
610
+ * @editor tungnx
611
+ * @version 3.1.1
612
  * @since 3.1.0
613
  */
614
+ public function sync_course_data( int $course_id ) {
615
  $user_curd = new LP_User_CURD();
616
  $course_curd = new LP_Course_CURD();
617
 
622
  }
623
 
624
  update_post_meta( $course_id, 'count_items', $count_items );
 
 
625
  }
626
 
627
  /**
647
  call_user_func( array( $this, $func ) );
648
  }
649
 
650
+ /***
651
+ * @editor tungnx
652
+ * @deprecated 4.0.7
653
+ * @reason not use on LP4, make CPU run high.
654
+ */
655
+ /*public function queue_sync_user_course_results( $course_id ) {
656
  global $wpdb;
657
  $query = $wpdb->prepare(
658
  "
697
  update_option( 'doing-sync-user-course-results', 'yes' );
698
  }
699
  }
700
+ }*/
701
 
702
  /**
703
  * Sync orders for each course
inc/curds/class-lp-course-curd.php CHANGED
@@ -308,22 +308,6 @@ if ( ! class_exists( 'LP_Course_CURD' ) ) {
308
  return $wpdb->get_col( $query );
309
  }
310
 
311
- /**
312
- * @param int $course_id
313
- */
314
- public function bg_update_items_format( $course_id ) {
315
- if ( ! get_option( 'update_items_format_' . $course_id ) ) {
316
- LP_Background_Global::add(
317
- 'update_items_format_' . $course_id,
318
- array(
319
- 'course_id' => $course_id,
320
- ),
321
- __CLASS__ . '::bg_update_items_format'
322
- );
323
- update_option( 'update_items_format_' . $course_id, 'yes' );
324
- }
325
- }
326
-
327
  public static function update_items_format( $item ) {
328
 
329
  if ( empty( $item['args']['course_id'] ) ) {
308
  return $wpdb->get_col( $query );
309
  }
310
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
311
  public static function update_items_format( $item ) {
312
 
313
  if ( empty( $item['args']['course_id'] ) ) {
inc/databases/class-lp-user-items-db.php CHANGED
@@ -35,48 +35,61 @@ class LP_User_Items_DB extends LP_Database {
35
  * @param int $user_id
36
  *
37
  * @return object
 
38
  */
39
  public function get_course_items_by_user_item_id( $user_item_id_by_course_id = 0, $user_id = 0 ) {
40
  if ( empty( $user_item_id_by_course_id ) || empty( $user_id ) ) {
41
  return null;
42
  }
43
 
44
- /**
45
- * Get cache
46
- *
47
- * Please clear cache when user action vs item. Ex: completed lesson, quiz. Start quiz...
48
- */
49
- $course_items = wp_cache_get(
50
- 'lp-course-items-' . $user_id . '-' . $user_item_id_by_course_id,
51
- 'lp-user-course-items'
 
 
52
  );
53
 
54
- if ( ! $course_items ) {
55
- $query = $this->wpdb->prepare(
56
- "
57
- SELECT * FROM {$this->tb_lp_user_items}
58
- WHERE parent_id = %d
59
- AND ref_type = %s
60
- AND user_id = %d
61
- ",
62
- $user_item_id_by_course_id,
63
- LP_COURSE_CPT,
64
- $user_id
65
- );
66
-
67
- $course_items = $this->wpdb->get_results( $query );
68
-
69
- // Set cache .
70
- wp_cache_set(
71
- 'lp-course-items-' . $user_id . '-' . $user_item_id_by_course_id,
72
- $course_items,
73
- 'lp-user-course-items'
74
- );
75
- }
76
 
77
  return $course_items;
78
  }
79
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
  /**
81
  * Remove items' of course and user learned
82
  *
35
  * @param int $user_id
36
  *
37
  * @return object
38
+ * @throws Exception
39
  */
40
  public function get_course_items_by_user_item_id( $user_item_id_by_course_id = 0, $user_id = 0 ) {
41
  if ( empty( $user_item_id_by_course_id ) || empty( $user_id ) ) {
42
  return null;
43
  }
44
 
45
+ $query = $this->wpdb->prepare(
46
+ "
47
+ SELECT * FROM {$this->tb_lp_user_items}
48
+ WHERE parent_id = %d
49
+ AND ref_type = %s
50
+ AND user_id = %d
51
+ ",
52
+ $user_item_id_by_course_id,
53
+ LP_COURSE_CPT,
54
+ $user_id
55
  );
56
 
57
+ $course_items = $this->wpdb->get_results( $query );
58
+
59
+ $this->check_execute_has_error();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
 
61
  return $course_items;
62
  }
63
 
64
+ /**
65
+ * Get data user_items by course_id, quiz_id, user_id
66
+ *
67
+ * @param [type] $course_id
68
+ * @param [type] $item_id
69
+ * @param [type] $user_id
70
+ * @return array
71
+ */
72
+ public function get_result_by_item_id( $course_id, $item_id, $user_id ) {
73
+ if ( empty( $course_id ) || empty( $item_id ) ) {
74
+ return false;
75
+ }
76
+
77
+ $query = $this->wpdb->prepare(
78
+ "SELECT * FROM {$this->tb_lp_user_items}
79
+ WHERE ref_id = %d
80
+ AND item_id = %d
81
+ AND user_id=%d
82
+ ORDER BY user_item_id DESC",
83
+ $course_id,
84
+ $item_id,
85
+ $user_id
86
+ );
87
+
88
+ $results = $this->wpdb->get_row( $query, ARRAY_A );
89
+
90
+ return $results;
91
+ }
92
+
93
  /**
94
  * Remove items' of course and user learned
95
  *
inc/libraries/wp-async-request.php CHANGED
@@ -1,12 +1,13 @@
1
  <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- exit;
4
- }
 
 
5
 
6
  /**
7
  * Abstract WP_Async_Request class.
8
  *
9
- * @package WP-Background-Processing
10
  * @abstract
11
  */
12
  abstract class WP_Async_Request {
@@ -94,10 +95,17 @@ abstract class WP_Async_Request {
94
  return $this->query_args;
95
  }
96
 
97
- return array(
98
  'action' => $this->identifier,
99
  'nonce' => wp_create_nonce( $this->identifier ),
100
  );
 
 
 
 
 
 
 
101
  }
102
 
103
  /**
@@ -110,7 +118,14 @@ abstract class WP_Async_Request {
110
  return $this->query_url;
111
  }
112
 
113
- return admin_url( 'admin-ajax.php' );
 
 
 
 
 
 
 
114
  }
115
 
116
  /**
@@ -123,13 +138,20 @@ abstract class WP_Async_Request {
123
  return $this->post_args;
124
  }
125
 
126
- return array(
127
  'timeout' => 0.01,
128
  'blocking' => false,
129
  'body' => $this->data,
130
  'cookies' => $_COOKIE,
131
  'sslverify' => apply_filters( 'https_local_ssl_verify', false ),
132
  );
 
 
 
 
 
 
 
133
  }
134
 
135
  /**
@@ -155,4 +177,5 @@ abstract class WP_Async_Request {
155
  * during the async request.
156
  */
157
  abstract protected function handle();
 
158
  }
1
  <?php
2
+ /**
3
+ * WP Async Request
4
+ *
5
+ * @package WP-Background-Processing
6
+ */
7
 
8
  /**
9
  * Abstract WP_Async_Request class.
10
  *
 
11
  * @abstract
12
  */
13
  abstract class WP_Async_Request {
95
  return $this->query_args;
96
  }
97
 
98
+ $args = array(
99
  'action' => $this->identifier,
100
  'nonce' => wp_create_nonce( $this->identifier ),
101
  );
102
+
103
+ /**
104
+ * Filters the post arguments used during an async request.
105
+ *
106
+ * @param array $url
107
+ */
108
+ return apply_filters( $this->identifier . '_query_args', $args );
109
  }
110
 
111
  /**
118
  return $this->query_url;
119
  }
120
 
121
+ $url = admin_url( 'admin-ajax.php' );
122
+
123
+ /**
124
+ * Filters the post arguments used during an async request.
125
+ *
126
+ * @param string $url
127
+ */
128
+ return apply_filters( $this->identifier . '_query_url', $url );
129
  }
130
 
131
  /**
138
  return $this->post_args;
139
  }
140
 
141
+ $args = array(
142
  'timeout' => 0.01,
143
  'blocking' => false,
144
  'body' => $this->data,
145
  'cookies' => $_COOKIE,
146
  'sslverify' => apply_filters( 'https_local_ssl_verify', false ),
147
  );
148
+
149
+ /**
150
+ * Filters the post arguments used during an async request.
151
+ *
152
+ * @param array $args
153
+ */
154
+ return apply_filters( $this->identifier . '_post_args', $args );
155
  }
156
 
157
  /**
177
  * during the async request.
178
  */
179
  abstract protected function handle();
180
+
181
  }
inc/libraries/wp-background-process.php CHANGED
@@ -1,13 +1,15 @@
1
  <?php
2
- if ( ! defined( 'ABSPATH' ) ) {
3
- exit;
4
- }
 
 
 
5
 
6
  /**
7
  * Abstract WP_Background_Process class.
8
  *
9
  * @abstract
10
- * @package WP-Background-Processing
11
  * @extends WP_Async_Request
12
  */
13
  abstract class WP_Background_Process extends WP_Async_Request {
@@ -106,7 +108,7 @@ abstract class WP_Background_Process extends WP_Async_Request {
106
  /**
107
  * Update queue
108
  *
109
- * @param string $key Key.
110
  * @param array $data Data.
111
  *
112
  * @return $this
@@ -270,18 +272,17 @@ abstract class WP_Background_Process extends WP_Async_Request {
270
  $key = $wpdb->esc_like( $this->identifier . '_batch_' ) . '%';
271
 
272
  $query = $wpdb->get_row( $wpdb->prepare( "
273
- SELECT *
274
- FROM {$table}
275
- WHERE {$column} LIKE %s
276
- ORDER BY {$key_column} ASC
277
- LIMIT 1
278
  ", $key ) );
279
- $batch = null;
280
- if( $query ){
281
- $batch = new stdClass();
282
- $batch->key = $query->$column;
283
- $batch->data = LP_Helper::maybe_unserialize( $query->$value_column );
284
- }
285
  return $batch;
286
  }
287
 
@@ -296,20 +297,20 @@ abstract class WP_Background_Process extends WP_Async_Request {
296
 
297
  do {
298
  $batch = $this->get_batch();
299
- if( $batch && isset($batch->data) && !empty($batch->data) ) {
300
- foreach ( $batch->data as $key => $value ) {
301
- $task = $this->task( $value );
302
- if ( false !== $task ) {
303
- $batch->data[ $key ] = $task;
304
- } else {
305
- unset( $batch->data[ $key ] );
306
- }
307
-
308
- if ( $this->time_exceeded() || $this->memory_exceeded() ) {
309
- // Batch limits reached.
310
- break;
311
- }
312
- }
313
  }
314
 
315
  // Update or delete current batch.
@@ -328,6 +329,8 @@ abstract class WP_Background_Process extends WP_Async_Request {
328
  } else {
329
  $this->complete();
330
  }
 
 
331
  }
332
 
333
  /**
@@ -363,12 +366,12 @@ abstract class WP_Background_Process extends WP_Async_Request {
363
  $memory_limit = '128M';
364
  }
365
 
366
- if ( ! $memory_limit || -1 === intval( $memory_limit ) ) {
367
  // Unlimited, set to 32GB.
368
  $memory_limit = '32000M';
369
  }
370
 
371
- return intval( $memory_limit ) * 1024 * 1024;
372
  }
373
 
374
  /**
@@ -405,20 +408,22 @@ abstract class WP_Background_Process extends WP_Async_Request {
405
  * Schedule cron healthcheck
406
  *
407
  * @access public
 
408
  * @param mixed $schedules Schedules.
 
409
  * @return mixed
410
  */
411
  public function schedule_cron_healthcheck( $schedules ) {
412
  $interval = apply_filters( $this->identifier . '_cron_interval', 5 );
413
 
414
  if ( property_exists( $this, 'cron_interval' ) ) {
415
- $interval = apply_filters( $this->identifier . '_cron_interval', $this->cron_interval_identifier );
416
  }
417
 
418
  // Adds every 5 minutes to the existing schedules.
419
  $schedules[ $this->identifier . '_cron_interval' ] = array(
420
  'interval' => MINUTE_IN_SECONDS * $interval,
421
- 'display' => sprintf( __( 'Every %d minutes', 'learnpress' ), $interval ),
422
  );
423
 
424
  return $schedules;
1
  <?php
2
+ /**
3
+ * WP Background Process
4
+ *
5
+ * @package WP-Background-Processing
6
+ * @source https://github.com/deliciousbrains/wp-background-processing
7
+ */
8
 
9
  /**
10
  * Abstract WP_Background_Process class.
11
  *
12
  * @abstract
 
13
  * @extends WP_Async_Request
14
  */
15
  abstract class WP_Background_Process extends WP_Async_Request {
108
  /**
109
  * Update queue
110
  *
111
+ * @param string $key Key.
112
  * @param array $data Data.
113
  *
114
  * @return $this
272
  $key = $wpdb->esc_like( $this->identifier . '_batch_' ) . '%';
273
 
274
  $query = $wpdb->get_row( $wpdb->prepare( "
275
+ SELECT *
276
+ FROM {$table}
277
+ WHERE {$column} LIKE %s
278
+ ORDER BY {$key_column} ASC
279
+ LIMIT 1
280
  ", $key ) );
281
+
282
+ $batch = new stdClass();
283
+ $batch->key = $query->$column;
284
+ $batch->data = maybe_unserialize( $query->$value_column );
285
+
 
286
  return $batch;
287
  }
288
 
297
 
298
  do {
299
  $batch = $this->get_batch();
300
+
301
+ foreach ( $batch->data as $key => $value ) {
302
+ $task = $this->task( $value );
303
+
304
+ if ( false !== $task ) {
305
+ $batch->data[ $key ] = $task;
306
+ } else {
307
+ unset( $batch->data[ $key ] );
308
+ }
309
+
310
+ if ( $this->time_exceeded() || $this->memory_exceeded() ) {
311
+ // Batch limits reached.
312
+ break;
313
+ }
314
  }
315
 
316
  // Update or delete current batch.
329
  } else {
330
  $this->complete();
331
  }
332
+
333
+ wp_die();
334
  }
335
 
336
  /**
366
  $memory_limit = '128M';
367
  }
368
 
369
+ if ( ! $memory_limit || - 1 === intval( $memory_limit ) ) {
370
  // Unlimited, set to 32GB.
371
  $memory_limit = '32000M';
372
  }
373
 
374
+ return wp_convert_hr_to_bytes( $memory_limit );
375
  }
376
 
377
  /**
408
  * Schedule cron healthcheck
409
  *
410
  * @access public
411
+ *
412
  * @param mixed $schedules Schedules.
413
+ *
414
  * @return mixed
415
  */
416
  public function schedule_cron_healthcheck( $schedules ) {
417
  $interval = apply_filters( $this->identifier . '_cron_interval', 5 );
418
 
419
  if ( property_exists( $this, 'cron_interval' ) ) {
420
+ $interval = apply_filters( $this->identifier . '_cron_interval', $this->cron_interval );
421
  }
422
 
423
  // Adds every 5 minutes to the existing schedules.
424
  $schedules[ $this->identifier . '_cron_interval' ] = array(
425
  'interval' => MINUTE_IN_SECONDS * $interval,
426
+ 'display' => sprintf( __( 'Every %d Minutes' ), $interval ),
427
  );
428
 
429
  return $schedules;
inc/user-item/class-lp-user-item-course.php CHANGED
@@ -123,12 +123,18 @@ class LP_User_Item_Course extends LP_User_Item implements ArrayAccess {
123
  );
124
  }
125
 
126
- $course_item = apply_filters(
127
- 'learn-press/user-course-item',
128
- LP_User_Item::get_item_object( $user_course_item ),
129
- $user_course_item,
130
- $this
131
- );
 
 
 
 
 
 
132
 
133
  if ( $course_item ) {
134
  $this->_items[ $item_id ] = $item_id;
@@ -138,6 +144,7 @@ class LP_User_Item_Course extends LP_User_Item implements ArrayAccess {
138
  $items[ $item_id ] = $course_item;
139
  }
140
  }
 
141
  LP_Object_Cache::set(
142
  $this->get_user_id() . '-' . $this->get_id(),
143
  $items,
@@ -181,7 +188,7 @@ class LP_User_Item_Course extends LP_User_Item implements ArrayAccess {
181
  }
182
 
183
  public function offsetGet( $offset ) {
184
- $items = $this->read_items();
185
 
186
  return $items && array_key_exists( $offset, $items ) ? $items[ $offset ] : false;
187
  }
123
  );
124
  }
125
 
126
+ $item_type = learn_press_get_post_type( $item_id );
127
+
128
+ switch ( $item_type ) {
129
+ case LP_QUIZ_CPT:
130
+ $course_item = new LP_User_Item_Quiz( $user_course_item );
131
+ break;
132
+ case LP_LESSON_CPT:
133
+ $course_item = new LP_User_Item( $user_course_item );
134
+ break;
135
+ }
136
+
137
+ $course_item = apply_filters( 'learn-press/user-course-item', $course_item, $user_course_item, $this );
138
 
139
  if ( $course_item ) {
140
  $this->_items[ $item_id ] = $item_id;
144
  $items[ $item_id ] = $course_item;
145
  }
146
  }
147
+
148
  LP_Object_Cache::set(
149
  $this->get_user_id() . '-' . $this->get_id(),
150
  $items,
188
  }
189
 
190
  public function offsetGet( $offset ) {
191
+ $items = $this->read_items( true );
192
 
193
  return $items && array_key_exists( $offset, $items ) ? $items[ $offset ] : false;
194
  }
inc/user-item/class-lp-user-item.php CHANGED
@@ -654,9 +654,6 @@ class LP_User_Item extends LP_Abstract_Object_Data implements ArrayAccess {
654
  case LP_LESSON_CPT:
655
  $item = new LP_User_Item( $data );
656
  break;
657
- case LP_QUIZ_CPT:
658
- $item = new LP_User_Item_Quiz( $data );
659
- break;
660
  }
661
 
662
  return apply_filters( 'learn-press/user-item-object', $item, $data, $item_type );
654
  case LP_LESSON_CPT:
655
  $item = new LP_User_Item( $data );
656
  break;
 
 
 
657
  }
658
 
659
  return apply_filters( 'learn-press/user-item-object', $item, $data, $item_type );
inc/user/abstract-lp-user.php CHANGED
@@ -663,20 +663,6 @@ if ( ! class_exists( 'LP_Abstract_User' ) ) {
663
  }
664
 
665
  return false;
666
- $item = false;
667
- if ( false !== ( $items = LP_Object_Cache::get(
668
- 'course-item-' . $this->get_id() . '-' . $course_id . '-' . $item_id,
669
- 'learn-press/user-course-items'
670
- ) ) ) {
671
- // Only get status of a newest record.
672
- if ( $last ) {
673
- $item = reset( $items );
674
- } else {
675
- $item = $items;
676
- }
677
- }
678
-
679
- return $item;
680
  }
681
 
682
  /**
663
  }
664
 
665
  return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
666
  }
667
 
668
  /**
inc/user/class-lp-user-factory.php CHANGED
@@ -18,11 +18,6 @@ class LP_User_Factory {
18
 
19
  public static $_deleted_users = array();
20
 
21
- /**
22
- * @var LP_Background_Clear_Temp_Users
23
- */
24
- // protected static $_background_clear_users = null;
25
-
26
  /**
27
  *
28
  */
@@ -43,21 +38,6 @@ class LP_User_Factory {
43
  add_action( 'learn-press/order/status-changed', array( __CLASS__, 'update_user_items' ), 10, 3 );
44
  }
45
 
46
- public static function clear_temp_users() {
47
- global $wpdb;
48
-
49
- $users = learn_press_get_temp_users();
50
-
51
- if ( $users ) {
52
- LP()->background( 'clear-temp-users' )->push_to_queue(
53
- array(
54
- 'action' => 'clear_temp_users',
55
- 'users' => $users,
56
- )
57
- );
58
- }
59
- }
60
-
61
  public static function update_user_items( $the_id, $old_status, $new_status ) {
62
  $order = learn_press_get_order( $the_id );
63
 
18
 
19
  public static $_deleted_users = array();
20
 
 
 
 
 
 
21
  /**
22
  *
23
  */
38
  add_action( 'learn-press/order/status-changed', array( __CLASS__, 'update_user_items' ), 10, 3 );
39
  }
40
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
  public static function update_user_items( $the_id, $old_status, $new_status ) {
42
  $order = learn_press_get_order( $the_id );
43
 
inc/user/lp-user-functions.php CHANGED
@@ -442,12 +442,7 @@ add_action( 'register_form', 'learn_press_user_become_teacher_registration_form'
442
  *
443
  * @return mixed
444
  */
445
- function learn_press_update_user_item_field(
446
- $fields,
447
- $where = false,
448
- $update_cache = true,
449
- $update_extra_fields_as_meta = false
450
- ) {
451
  global $wpdb;
452
 
453
  // Table fields
@@ -667,6 +662,7 @@ function learn_press_get_user_item( $where, $single = true ) {
667
  SELECT *
668
  FROM {$wpdb->prefix}learnpress_user_items
669
  WHERE " . join( ' AND ', $where_str ) . '
 
670
  ',
671
  $where
672
  );
@@ -833,9 +829,9 @@ function _learn_press_update_updated_time_user_item_meta( $meta_id, $object_id,
833
 
834
  /**
835
  * @param $status
836
- * @param int $quiz_id
837
- * @param int $user_id
838
- * @param int $course_id
839
  *
840
  * @return bool|mixed
841
  */
@@ -1051,7 +1047,7 @@ function learn_press_update_user_option( $name, $value, $id = 0 ) {
1051
 
1052
  /**
1053
  * @param $name
1054
- * @param int $id
1055
  *
1056
  * @return bool
1057
  */
@@ -1073,7 +1069,7 @@ function learn_press_delete_user_option( $name, $id = 0 ) {
1073
 
1074
  /**
1075
  * @param $name
1076
- * @param int $id
1077
  *
1078
  * @return bool
1079
  */
@@ -1531,12 +1527,12 @@ function learn_press_get_user_role( $user_id ) {
1531
  function learn_press_create_user_item( $args = array(), $wp_error = false ) {
1532
  global $wpdb;
1533
 
1534
- $currentTime = new LP_Datetime();
1535
- $defaults = array(
1536
  'user_id' => get_current_user_id(),
1537
  'item_id' => '',
1538
- 'start_time' => $currentTime->toSql( false ),
1539
  'end_time' => '',
 
1540
  'item_type' => '',
1541
  'status' => '',
1542
  'ref_id' => 0,
@@ -1545,10 +1541,10 @@ function learn_press_create_user_item( $args = array(), $wp_error = false ) {
1545
  'create_meta' => array(),
1546
  );
1547
 
1548
- $itemData = wp_parse_args( $args, $defaults );
1549
 
1550
  // Validate item_id and post type
1551
- if ( empty( $itemData['item_id'] ) ) {
1552
  if ( $wp_error ) {
1553
  return new WP_Error( 'invalid_item_id', __( 'Invalid item id.', 'learnpress' ) );
1554
  }
@@ -1556,32 +1552,32 @@ function learn_press_create_user_item( $args = array(), $wp_error = false ) {
1556
  return 0;
1557
  }
1558
 
1559
- if ( empty( $itemData['item_type'] ) && $post_type = learn_press_get_post_type( $itemData['item_id'] ) ) {
1560
- $itemData['item_type'] = $post_type;
1561
  }
1562
 
1563
  // Get id and type of ref if they are null
1564
- if ( ! empty( $itemData['parent_id'] ) && ( empty( $itemData['ref_id'] ) || ( empty( $itemData['ref_type'] ) ) ) ) {
1565
  $parent = $wpdb->get_row(
1566
  $wpdb->prepare(
1567
  "SELECT * FROM {$wpdb->learnpress_user_items} WHERE %d",
1568
- $itemData['parent_id']
1569
  )
1570
  );
1571
 
1572
  if ( $parent ) {
1573
- if ( empty( $itemData['ref_id'] ) ) {
1574
- $itemData['ref_id'] = $parent->item_id;
1575
  }
1576
 
1577
- if ( empty( $itemData['ref_type'] ) ) {
1578
- $itemData['ref_type'] = $parent->item_type;
1579
  }
1580
  }
1581
  }
1582
 
1583
  // Filter
1584
- if ( ! $itemData = apply_filters( 'learn-press/create-user-item-data', $itemData ) ) {
1585
  if ( $wp_error ) {
1586
  return new WP_Error( 'invalid_item_data', __( 'Invalid item data.', 'learnpress' ) );
1587
  }
@@ -1589,17 +1585,17 @@ function learn_press_create_user_item( $args = array(), $wp_error = false ) {
1589
  return 0;
1590
  }
1591
 
1592
- do_action( 'learn-press/before-create-user-item', $itemData );
1593
 
1594
- $createMeta = ! empty( $itemData['create_meta'] ) ? $itemData['create_meta'] : false;
1595
 
1596
- if ( $createMeta ) {
1597
- unset( $itemData['create_meta'] );
1598
  }
1599
 
1600
- $userItem = new LP_User_Item( $itemData );
1601
 
1602
- $result = $userItem->update( true, false );
1603
 
1604
  if ( ! $result || is_wp_error( $result ) ) {
1605
 
@@ -1610,22 +1606,22 @@ function learn_press_create_user_item( $args = array(), $wp_error = false ) {
1610
  return 0;
1611
  }
1612
 
1613
- do_action( 'learn-press/created-user-item', $userItem, $itemData );
1614
 
1615
- $createMeta = apply_filters( 'learn-press/create-user-item-meta', $createMeta, $itemData );
1616
- if ( ! $createMeta ) {
1617
- return $userItem;
1618
  }
1619
 
1620
- do_action( 'learn-press/before-create-user-item-meta', $createMeta );
1621
 
1622
- foreach ( $createMeta as $key => $value ) {
1623
- learn_press_update_user_item_meta( $userItem->get_user_item_id(), $key, $value );
1624
  }
1625
 
1626
- do_action( 'learn-press/created-user-item-meta', $userItem, $createMeta );
1627
 
1628
- return $userItem;
1629
  }
1630
 
1631
  /**
@@ -1640,9 +1636,10 @@ function learn_press_create_user_item_for_quiz( $args = array(), $wp_error = fal
1640
  $item_data = wp_parse_args(
1641
  $args,
1642
  array(
1643
- 'item_type' => LP_QUIZ_CPT,
1644
- 'status' => 'started',
1645
- 'user_id' => get_current_user_id(),
 
1646
  )
1647
  );
1648
 
@@ -1656,6 +1653,26 @@ function learn_press_create_user_item_for_quiz( $args = array(), $wp_error = fal
1656
  return $user_item;
1657
  }
1658
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1659
  /**
1660
  * Create new user item prepare for user starts a quiz
1661
  * Update error retry course not work - Nhamdv.
442
  *
443
  * @return mixed
444
  */
445
+ function learn_press_update_user_item_field( $fields, $where = false, $update_cache = true, $update_extra_fields_as_meta = false ) {
 
 
 
 
 
446
  global $wpdb;
447
 
448
  // Table fields
662
  SELECT *
663
  FROM {$wpdb->prefix}learnpress_user_items
664
  WHERE " . join( ' AND ', $where_str ) . '
665
+ ORDER BY user_item_id DESC
666
  ',
667
  $where
668
  );
829
 
830
  /**
831
  * @param $status
832
+ * @param int $quiz_id
833
+ * @param int $user_id
834
+ * @param int $course_id
835
  *
836
  * @return bool|mixed
837
  */
1047
 
1048
  /**
1049
  * @param $name
1050
+ * @param int $id
1051
  *
1052
  * @return bool
1053
  */
1069
 
1070
  /**
1071
  * @param $name
1072
+ * @param int $id
1073
  *
1074
  * @return bool
1075
  */
1527
  function learn_press_create_user_item( $args = array(), $wp_error = false ) {
1528
  global $wpdb;
1529
 
1530
+ $defaults = array(
 
1531
  'user_id' => get_current_user_id(),
1532
  'item_id' => '',
1533
+ 'start_time' => current_time( 'mysql', true ),
1534
  'end_time' => '',
1535
+ 'graduation' => '',
1536
  'item_type' => '',
1537
  'status' => '',
1538
  'ref_id' => 0,
1541
  'create_meta' => array(),
1542
  );
1543
 
1544
+ $item_data = wp_parse_args( $args, $defaults );
1545
 
1546
  // Validate item_id and post type
1547
+ if ( empty( $item_data['item_id'] ) ) {
1548
  if ( $wp_error ) {
1549
  return new WP_Error( 'invalid_item_id', __( 'Invalid item id.', 'learnpress' ) );
1550
  }
1552
  return 0;
1553
  }
1554
 
1555
+ if ( empty( $item_data['item_type'] ) && $post_type = learn_press_get_post_type( $item_data['item_id'] ) ) {
1556
+ $item_data['item_type'] = $post_type;
1557
  }
1558
 
1559
  // Get id and type of ref if they are null
1560
+ if ( ! empty( $item_data['parent_id'] ) && ( empty( $item_data['ref_id'] ) || ( empty( $item_data['ref_type'] ) ) ) ) {
1561
  $parent = $wpdb->get_row(
1562
  $wpdb->prepare(
1563
  "SELECT * FROM {$wpdb->learnpress_user_items} WHERE %d",
1564
+ $item_data['parent_id']
1565
  )
1566
  );
1567
 
1568
  if ( $parent ) {
1569
+ if ( empty( $item_data['ref_id'] ) ) {
1570
+ $item_data['ref_id'] = $parent->item_id;
1571
  }
1572
 
1573
+ if ( empty( $item_data['ref_type'] ) ) {
1574
+ $item_data['ref_type'] = $parent->item_type;
1575
  }
1576
  }
1577
  }
1578
 
1579
  // Filter
1580
+ if ( ! $item_data = apply_filters( 'learn-press/create-user-item-data', $item_data ) ) {
1581
  if ( $wp_error ) {
1582
  return new WP_Error( 'invalid_item_data', __( 'Invalid item data.', 'learnpress' ) );
1583
  }
1585
  return 0;
1586
  }
1587
 
1588
+ do_action( 'learn-press/before-create-user-item', $item_data );
1589
 
1590
+ $create_meta = ! empty( $item_data['create_meta'] ) ? $item_data['create_meta'] : false;
1591
 
1592
+ if ( $create_meta ) {
1593
+ unset( $item_data['create_meta'] );
1594
  }
1595
 
1596
+ $user_item = new LP_User_Item( $item_data );
1597
 
1598
+ $result = $user_item->update( true, false );
1599
 
1600
  if ( ! $result || is_wp_error( $result ) ) {
1601
 
1606
  return 0;
1607
  }
1608
 
1609
+ do_action( 'learn-press/created-user-item', $user_item, $item_data );
1610
 
1611
+ $create_meta = apply_filters( 'learn-press/create-user-item-meta', $create_meta, $item_data );
1612
+ if ( ! $create_meta ) {
1613
+ return $user_item;
1614
  }
1615
 
1616
+ do_action( 'learn-press/before-create-user-item-meta', $create_meta );
1617
 
1618
+ foreach ( $create_meta as $key => $value ) {
1619
+ learn_press_update_user_item_meta( $user_item->get_user_item_id(), $key, $value );
1620
  }
1621
 
1622
+ do_action( 'learn-press/created-user-item-meta', $user_item, $create_meta );
1623
 
1624
+ return $user_item;
1625
  }
1626
 
1627
  /**
1636
  $item_data = wp_parse_args(
1637
  $args,
1638
  array(
1639
+ 'item_type' => LP_QUIZ_CPT,
1640
+ 'status' => 'started',
1641
+ 'graduation' => 'in-progress',
1642
+ 'user_id' => get_current_user_id(),
1643
  )
1644
  );
1645
 
1653
  return $user_item;
1654
  }
1655
 
1656
+ /**
1657
+ * Get list user_item_id for Quiz in table learnpress_user_items
1658
+ *
1659
+ * @param int $quiz_id
1660
+ * @param int $course_id
1661
+ * @return array || false
1662
+ */
1663
+ function learn_press_isset_user_item_for_quiz( $quiz_id, $course_id ) {
1664
+ global $wpdb;
1665
+
1666
+ $query = $wpdb->prepare( "SELECT user_item_id FROM $wpdb->learnpress_user_items WHERE ref_id=%d AND item_id=%d", $course_id, $quiz_id );
1667
+ $col = $wpdb->get_col( $query );
1668
+
1669
+ if ( ! empty( $col ) ) {
1670
+ return $col;
1671
+ } else {
1672
+ return false;
1673
+ }
1674
+ }
1675
+
1676
  /**
1677
  * Create new user item prepare for user starts a quiz
1678
  * Update error retry course not work - Nhamdv.
learnpress.php CHANGED
@@ -4,7 +4,7 @@
4
  * Plugin URI: http://thimpress.com/learnpress
5
  * Description: LearnPress is a WordPress complete solution for creating a Learning Management System (LMS). It can help you to create courses, lessons and quizzes.
6
  * Author: ThimPress
7
- * Version: 4.0.6
8
  * Author URI: http://thimpress.com
9
  * Requires at least: 3.8
10
  * Tested up to: 5.7
@@ -172,75 +172,6 @@ if ( ! class_exists( 'LearnPress' ) ) {
172
  }
173
  }
174
 
175
- public function init_background_processes() {
176
- $supports = apply_filters(
177
- 'learn-press/background-processes',
178
- array(
179
- 'emailer' => 'emailer',
180
- 'installer' => 'installer',
181
- 'query-items' => 'query-items',
182
- 'schedule-items' => 'schedule-items',
183
- 'global' => 'global',
184
- 'clear-temp-users' => 'clear-temp-users',
185
- 'sync-data' => 'sync-data',
186
- )
187
- );
188
-
189
- foreach ( $supports as $name => $file ) {
190
- if ( ! is_file( $file ) || ! file_exists( $file ) || preg_match( '~.php$~', $file ) ) {
191
- $file = LP_PLUGIN_PATH . "/inc/background-process/class-lp-background-{$file}.php";
192
- }
193
-
194
- if ( file_exists( $file ) && is_readable( $file ) ) {
195
- $this->backgrounds[ $name ] = include_once $file;
196
- }
197
- }
198
- }
199
-
200
- /**
201
- * Add new task to a background process.
202
- *
203
- * @param mixed $data .
204
- * @param string $background .
205
- *
206
- * @return LP_Abstract_Background_Process|bool
207
- * @since 3.0.8
208
- * @editor tungnx | comment this function
209
- */
210
- /*public function add_background_task( $data, $background = 'global' ) {
211
- if ( isset( $this->backgrounds[ $background ] ) ) {
212
- $this->backgrounds[ $background ]->push_to_queue( $data );
213
-
214
- return $this->backgrounds[ $background ];
215
- }
216
-
217
- return false;
218
- }*/
219
-
220
- /**
221
- * Return a background instance.
222
- *
223
- * @param string $name
224
- *
225
- * @return LP_Abstract_Background_Process|bool
226
- * @since 3.0.8
227
- */
228
- public function background( $name ) {
229
- if ( ! did_action( 'plugins_loaded' ) ) {
230
- _doing_it_wrong(
231
- __CLASS__ . '::' . __FUNCTION__,
232
- 'should call after \'plugins_loaded\' action',
233
- '3.0.8'
234
- );
235
- }
236
-
237
- if ( isset( $this->backgrounds[ $name ] ) ) {
238
- return $this->backgrounds[ $name ];
239
- }
240
-
241
- return false;
242
- }
243
-
244
  /**
245
  * Defines database table names.
246
  */
@@ -551,30 +482,8 @@ if ( ! class_exists( 'LearnPress' ) ) {
551
  */
552
  public function on_deactivate() {
553
  do_action( 'learn-press/deactivate', $this );
554
- //$this->remove_cron();
555
  }
556
 
557
- /*protected function add_cron() {
558
- add_filter( 'cron_schedules', array( $this, 'cron_schedules' ) );
559
-
560
- if ( ! wp_next_scheduled( 'learn_press_schedule_items' ) ) {
561
- wp_schedule_event( time(), 'lp_cron_schedule_items', 'learn_press_schedule_items' );
562
- }
563
- }*/
564
-
565
- /*protected function remove_cron() {
566
- wp_clear_scheduled_hook( 'learn_press_schedule_items' );
567
- }*/
568
-
569
- /*public function cron_schedules( $schedules ) {
570
- $schedules['lp_cron_schedule_items'] = array(
571
- 'interval' => 15,
572
- 'display' => esc_html__( 'Every 3 Minutes', 'learnpress' ),
573
- );
574
-
575
- return $schedules;
576
- }*/
577
-
578
  /**
579
  * Trigger WP loaded actions.
580
  *
@@ -618,11 +527,10 @@ if ( ! class_exists( 'LearnPress' ) ) {
618
  * @editor tungnx
619
  */
620
  public function plugin_loaded() {
621
- //$this->add_cron();
622
  $this->init();
623
 
624
- // Background.
625
- $this->init_background_processes();
626
 
627
  require_once 'inc/lp-template-hooks.php';
628
 
4
  * Plugin URI: http://thimpress.com/learnpress
5
  * Description: LearnPress is a WordPress complete solution for creating a Learning Management System (LMS). It can help you to create courses, lessons and quizzes.
6
  * Author: ThimPress
7
+ * Version: 4.0.7-beta-1
8
  * Author URI: http://thimpress.com
9
  * Requires at least: 3.8
10
  * Tested up to: 5.7
172
  }
173
  }
174
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
175
  /**
176
  * Defines database table names.
177
  */
482
  */
483
  public function on_deactivate() {
484
  do_action( 'learn-press/deactivate', $this );
 
485
  }
486
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
487
  /**
488
  * Trigger WP loaded actions.
489
  *
527
  * @editor tungnx
528
  */
529
  public function plugin_loaded() {
 
530
  $this->init();
531
 
532
+ //Todo: tungnx - remove this code after handle ajax on page learn-press-addons
533
+ require_once 'inc/background-process/class-lp-background-query-items.php';
534
 
535
  require_once 'inc/lp-template-hooks.php';
536
 
readme.txt CHANGED
@@ -5,7 +5,7 @@ Tags: elearning, education, course, lms, learning management system
5
  Requires at least: 5.6
6
  Tested up to: 5.7
7
  Requires PHP: 7.0
8
- Stable tag: 4.0.6
9
  License: GPLv2 or later
10
  License URI: https://www.gnu.org/licenses/gpl-2.0.html
11
 
@@ -204,7 +204,7 @@ https://www.transifex.com/projects/p/learnpress/
204
  ~ Fixed: show html title question
205
  ~ Fixed: Order change status from "completed" to "pending" => user can't learn courses in this order
206
  ~ Added: Option "Logout Redirect"
207
- ~ Fixed: Set default sidebar curriculumn will be hide on mobile
208
  ~ Modify: Remove course on Overview tab when enable "Publish Profile"
209
  ~ Fixed: Elementor pro make archive course show wrong
210
 
5
  Requires at least: 5.6
6
  Tested up to: 5.7
7
  Requires PHP: 7.0
8
+ Stable tag: 4.0.7-beta-1
9
  License: GPLv2 or later
10
  License URI: https://www.gnu.org/licenses/gpl-2.0.html
11
 
204
  ~ Fixed: show html title question
205
  ~ Fixed: Order change status from "completed" to "pending" => user can't learn courses in this order
206
  ~ Added: Option "Logout Redirect"
207
+ ~ Fixed: Set default sidebar curriculum will be hide on mobile
208
  ~ Modify: Remove course on Overview tab when enable "Publish Profile"
209
  ~ Fixed: Elementor pro make archive course show wrong
210
 
templates/content-quiz/js.php CHANGED
@@ -117,12 +117,16 @@ if ( $total_question ) :
117
  <div id="learn-press-quiz-app"></div>
118
 
119
  <script>
120
- LP.Hook.addAction('course-ready', () => {
121
- LP.quiz.init(
122
- '#learn-press-quiz-app',
123
- <?php echo json_encode( $js ); ?>
124
- )
125
- });
 
 
 
 
126
  </script>
127
 
128
  <?php
117
  <div id="learn-press-quiz-app"></div>
118
 
119
  <script>
120
+ document.addEventListener( 'DOMContentLoaded', () => {
121
+ if ( typeof LP !== 'undefined' ) {
122
+ LP.Hook.addAction('course-ready', () => {
123
+ LP.quiz.init(
124
+ '#learn-press-quiz-app',
125
+ <?php echo json_encode( $js ); ?>
126
+ )
127
+ });
128
+ }
129
+ });
130
  </script>
131
 
132
  <?php