PluginProbe ʕ •ᴥ•ʔ
Tutor LMS – eLearning and online course solution / 3.9.3
Tutor LMS – eLearning and online course solution v3.9.3
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 / migrations / BatchProcessor.php
tutor / migrations Last commit date
Contracts 9 months ago BatchProcessor.php 9 months ago Migration.php 7 months ago ProcessByWcMigrator.php 9 months ago QuizAttemptMigrator.php 9 months ago
BatchProcessor.php
297 lines
1 <?php
2 /**
3 * Class to handle process large amount of data with batch.
4 *
5 * @package Tutor
6 * @author Themeum <support@themeum.com>
7 * @link https://themeum.com
8 * @since 3.8.0
9 */
10
11 namespace Tutor\Migrations;
12
13 use Tutor\Migrations\Contracts\BulkProcessor;
14 use Tutor\Migrations\Contracts\SingleProcessor;
15
16 /**
17 * Class BatchProcessor
18 *
19 * @since 3.8.0
20 */
21 abstract class BatchProcessor {
22 /**
23 * Batch size.
24 *
25 * @since 3.8.0
26 *
27 * @var int
28 */
29 protected $batch_size;
30
31 /**
32 * Schedule interval
33 *
34 * @since 3.8.0
35 *
36 * @var int
37 */
38 protected $schedule_interval;
39
40 /**
41 * Progress option name to keep track of each process status.
42 *
43 * @since 3.8.0
44 *
45 * @var string
46 */
47 protected $progress_option;
48
49 /**
50 * Manage child class as singleton behavior.
51 *
52 * @since 3.8.0
53 *
54 * @var object
55 */
56 protected static $instances = array();
57
58 /**
59 * Action name to invoke wp-cron.
60 *
61 * @since 3.8.0
62 *
63 * @var string
64 */
65 protected $action;
66
67 /**
68 * Name of the process.
69 *
70 * @since 3.8.0
71 *
72 * @var string
73 */
74 protected $name;
75
76 /**
77 * Constructor.
78 *
79 * @since 3.8.0
80 *
81 * @throws \Exception If action is not set.
82 */
83 protected function __construct() {
84 if ( empty( $this->action ) ) {
85 throw new \Exception( 'Action property must be defined in the subclass.' );
86 }
87
88 $this->progress_option = "tutor_batch_processor_{$this->action}";
89 add_action( $this->action, array( $this, 'process_batch' ) );
90 }
91
92 /**
93 * Get child class instance.
94 *
95 * @since 3.8.0
96 *
97 * @return object
98 */
99 public static function instance() {
100 if ( ! isset( static::$instances[ static::class ] ) ) {
101 static::$instances[ static::class ] = new static();
102 }
103 return static::$instances[ static::class ];
104 }
105
106 /**
107 * Get items to process.
108 * Must be implemented in child class.
109 *
110 * @since 3.8.0
111 *
112 * @param int $offset offset.
113 * @param int $limit limit.
114 *
115 * @return array
116 */
117 abstract protected function get_items( $offset, $limit) : array;
118
119 /**
120 * Get total items to process.
121 * Must be implemented in child class.
122 *
123 * @since 3.8.0
124 *
125 * @return int
126 */
127 abstract protected function get_total_items() : int;
128
129 /**
130 * Schedule the batch processing.
131 *
132 * This method checks if the action is already scheduled, and if not, it schedules a single event
133 * to trigger the batch processing after the specified interval.
134 *
135 * @since 3.8.0
136 *
137 * @return void
138 */
139 public function schedule() {
140 if ( ! wp_next_scheduled( $this->action ) ) {
141 wp_schedule_single_event( time() + $this->schedule_interval, $this->action );
142 }
143 }
144
145 /**
146 * Process a batch of items.
147 *
148 * This method retrieves a batch of items based on the current offset and batch size,
149 * processes each item, updates the progress, and schedules the next batch processing.
150 *
151 * @since 3.8.0
152 *
153 * @return void
154 *
155 * @throws \Exception If not implemented any interface on child class..
156 */
157 public function process_batch() {
158 $progress = get_option(
159 $this->progress_option,
160 array(
161 'name' => $this->name,
162 'started_at' => gmdate( 'Y-m-d H:i:s' ),
163 'completed_at' => null,
164 'offset' => 0,
165 'completed' => false,
166 'total_items' => null,
167 'total_batch' => null,
168 'per_batch' => $this->batch_size,
169 'current_batch' => 1,
170 )
171 );
172
173 if ( $progress['completed'] ) {
174 return;
175 }
176
177 // Set total_items and total_batch if not already set.
178 if ( is_null( $progress['total_items'] ) ) {
179 $progress['total_items'] = $this->get_total_items();
180 $progress['total_batch'] = (int) ceil( $progress['total_items'] / $progress['per_batch'] );
181 }
182
183 $items = $this->get_items( $progress['offset'], $this->batch_size );
184
185 if ( empty( $items ) ) {
186 $this->mark_complete();
187 return;
188 }
189
190 if ( $this instanceof BulkProcessor ) {
191 $this->process_items( $items );
192 } elseif ( $this instanceof SingleProcessor ) {
193 foreach ( $items as $item ) {
194 $this->process_item( $item );
195 }
196 } else {
197 throw new \Exception( 'Child class must implement SingleProcessor or BulkProcessor interface.' );
198 }
199
200 $progress['offset'] += count( $items );
201 $progress['current_batch'] = (int) ceil( $progress['offset'] / $progress['per_batch'] );
202 update_option( $this->progress_option, $progress );
203
204 wp_schedule_single_event( time() + $this->schedule_interval, $this->action );
205 }
206
207 /**
208 * Mark the batch processing as complete.
209 *
210 * This method updates the progress option to indicate that the batch processing is complete
211 * and calls the optional `on_complete` method for any additional actions needed upon completion.
212 *
213 * @since 3.8.0
214 *
215 * @return void
216 */
217 protected function mark_complete() {
218 $data = wp_parse_args(
219 array(
220 'offset' => 0,
221 'completed' => true,
222 'completed_at' => gmdate( 'Y-m-d H:i:s' ),
223 ),
224 $this->get_stats()
225 );
226
227 update_option( $this->progress_option, $data );
228
229 $this->on_complete();
230 }
231
232 /**
233 * Optional method to override in child classes to perform actions when the batch processing is complete.
234 *
235 * @since 3.8.0
236 *
237 * @return void
238 */
239 protected function on_complete() {}
240
241 /**
242 * Check is complete.
243 *
244 * @since 3.8.0
245 *
246 * @return boolean
247 */
248 public function is_completed(): bool {
249 $progress = get_option( $this->progress_option, array() );
250 return ! empty( $progress['completed'] );
251 }
252
253 /**
254 * Get the progress option name.
255 *
256 * @since 3.8.0
257 *
258 * @return string
259 */
260 public function get_progress_option_name() {
261 return $this->progress_option;
262 }
263
264 /**
265 * Get the progress stats.
266 *
267 * @since 3.8.0
268 *
269 * @return array
270 */
271 public function get_stats(): array {
272 $progress = get_option( $this->progress_option, array() );
273 return wp_parse_args(
274 $progress,
275 array(
276 'offset' => 0,
277 'completed' => false,
278 'total_items' => 0,
279 'total_batch' => 0,
280 'per_batch' => $this->batch_size,
281 'current_batch' => 1,
282 )
283 );
284 }
285
286 /**
287 * Reset the progress option.
288 *
289 * @since 3.8.0
290 *
291 * @return void
292 */
293 public function reset() {
294 delete_option( $this->progress_option );
295 }
296 }
297