Diff: STRATO-apps/wordpress_03/app/wp-content/plugins/tutor-pro/tools/Exporter.php

Keine Baseline-Datei – Diff nur gegen leer.
Zur Liste
1 -
1 + <?php
2 + /**
3 + * TutorPro Exporter
4 + *
5 + * @package TutorPro\Tools
6 + * @author Themeum<support@themeum.com>
7 + * @link https://themeum.com
8 + * @since 3.6.0
9 + */
10 +
11 + namespace TutorPro\Tools;
12 +
13 + use TUTOR\Reviews;
14 + use TutorPro\ContentBank\Models\CollectionModel;
15 +
16 + if ( ! defined( 'ABSPATH' ) ) {
17 + exit;
18 + }
19 +
20 + /**
21 + * Handling export functionality.
22 + *
23 + * @since 3.6.0
24 + */
25 + class Exporter {
26 +
27 + /**
28 + * Course ids to export
29 + *
30 + * @since 3.6.0
31 + *
32 + * @var array
33 + */
34 + private $course_ids = array();
35 +
36 + /**
37 + * Bundle ids to export
38 + *
39 + * @since 3.6.0
40 + *
41 + * @var array
42 + */
43 + private $bundle_ids = array();
44 +
45 + /**
46 + * Collection ids to export
47 + *
48 + * @since 3.7.0
49 + *
50 + * @var array
51 + */
52 + private $collection_ids = array();
53 +
54 + /**
55 + * Course content types to export
56 + *
57 + * @since 3.6.0
58 + *
59 + * @var array
60 + */
61 + private $content_types = array();
62 +
63 + /**
64 + * Export settings
65 + *
66 + * @since 3.6.0
67 + *
68 + * @var array
69 + */
70 + private $export_settings = false;
71 +
72 + /**
73 + * Membership ids to export.
74 + *
75 + * @since 3.8.1
76 + *
77 + * @var array
78 + */
79 + private $membership_plan_ids = array();
80 +
81 + /**
82 + * Keep media files
83 + *
84 + * @since 3.6.0
85 + *
86 + * @var array
87 + */
88 + private $keep_media_files = false;
89 +
90 + /**
91 + * Unique identifier for the current job or export/import process.
92 + *
93 + * @since 3.8.1
94 + *
95 + * @var int
96 + */
97 + private $job_id;
98 +
99 + /**
100 + * Version for the JSON file
101 + *
102 + * @since 3.6.0
103 + */
104 + const SCHEMA_VERSION = '2.0.0';
105 +
106 + /**
107 + * Exportable content types other than posts.
108 + *
109 + * @since 3.6.0
110 + */
111 + const TYPE_SETTINGS = 'settings';
112 + const TYPE_ATTACHMENTS = 'attachments';
113 +
114 + /**
115 + * Content bank
116 + *
117 + * @since 3.7.0
118 + */
119 + const TYPE_CONTENT_BANK = 'content_bank';
120 +
121 + /**
122 + * Questions
123 + *
124 + * @since 3.7.1
125 + */
126 + const TYPE_QUESTIONS = 'questions';
127 +
128 +
129 + /**
130 + * Keep user data
131 + *
132 + * @since 3.8.1
133 + *
134 + * @var bool
135 + */
136 + private $keep_user_data = false;
137 +
138 + /**
139 + * Export option name
140 + *
141 + * Each job id will be concat with this option name
142 + *
143 + * @since 3.6.0
144 + */
145 + const OPT_NAME = 'tutor_pro_export_';
146 +
147 + /**
148 + * Add-ons List
149 + *
150 + * @since 3.8.1
151 + */
152 + const ADD_ONS = array(
153 + self::TYPE_CONTENT_BANK => 'content-bank',
154 + 'course-bundle' => 'course-bundle',
155 + );
156 +
157 + /**
158 + * Membership Plans
159 + *
160 + * @since 3.8.1
161 + */
162 + const TYPE_MEMBERSHIP_PLANS = 'membership_plans';
163 +
164 + /**
165 + * Current sub file being processed.
166 + *
167 + * @since 3.8.1
168 + *
169 + * @var string
170 + */
171 + private $current_sub_file;
172 +
173 + /**
174 + * Current bundle course ID being processed.
175 + *
176 + * @since 3.8.1
177 + *
178 + * @var int
179 + */
180 + private $current_bundle_course_id;
181 +
182 + /**
183 + * Current course sub file being processed.
184 + *
185 + * @since 3.8.1
186 + *
187 + * @var string
188 + */
189 + private $current_course_sub_file;
190 +
191 + /**
192 + * Holds the job data associated with the current export process.
193 + *
194 + * @since 3.8.1
195 + *
196 + * @var array
197 + */
198 + private $job_data;
199 +
200 + const BUNDLE = 'bundle';
201 + const ENROLLMENTS = 'enrollments';
202 + const PLANS = 'plans';
203 + const ORDERS = 'orders';
204 + const SUBSCRIPTIONS = 'subscriptions';
205 + const COURSES = 'courses';
206 + const COURSE = 'course';
207 + const PROGRESS = 'progress';
208 + const REVIEWS = 'reviews';
209 + const OPTION_USER_IDS = 'tutor_pro_user_ids_for_';
210 + const GRADE_BOOKS_SETTINGS = 'grade_books_settings';
211 +
212 + /**
213 + * Indicates whether grade book settings have been retrieved or set.
214 + *
215 + * @since 3.8.1
216 + *
217 + * @var bool|array
218 + */
219 + private $grade_book_settings = false;
220 +
221 + /**
222 + * List of content types that represent single export settings.
223 + *
224 + * @since 3.8.1
225 + *
226 + * @var string[]
227 + */
228 + const SETTINGS_CONTENT_TYPES = array(
229 + self::TYPE_SETTINGS,
230 + self::GRADE_BOOKS_SETTINGS,
231 + );
232 +
233 +
234 + /**
235 + * Get exportable main types.
236 + *
237 + * @since 3.6.0
238 + *
239 + * @since 3.7.1 $context param added.
240 + *
241 + * @param string $context Context content-bank or empty.
242 + *
243 + * @return array
244 + */
245 + public function get_exportable_content( string $context = '' ): array {
246 + $contents = array(
247 + array(
248 + 'key' => tutor()->course_post_type,
249 + 'label' => __( 'Courses', 'tutor-pro' ),
250 + 'contents' => $this->get_exportable_sub_contents(),
251 + ),
252 + array(
253 + 'key' => self::TYPE_SETTINGS,
254 + 'label' => __( 'Settings', 'tutor-pro' ),
255 + 'contents' => array(),
256 + ),
257 + array(
258 + 'key' => 'keep_media_files',
259 + 'label' => __( 'Keep media files', 'tutor-pro' ),
260 + 'contents' => array(),
261 + ),
262 + array(
263 + 'key' => 'keep_user_data',
264 + 'label' => __( 'Keep user data', 'tutor-pro' ),
265 + 'contents' => array(),
266 + ),
267 + );
268 +
269 + // Add enabled add-ons.
270 + foreach ( self::ADD_ONS as $key => $value ) {
271 + if ( tutor_utils()->is_addon_enabled( $value ) ) {
272 + $contents[] = array(
273 + 'key' => $key,
274 + 'label' => __( ucwords( str_replace( array( '_', '-' ), ' ', $key ) ), 'tutor-pro' ),
275 + 'contents' => array(),
276 + );
277 + }
278 + }
279 +
280 + if ( self::TYPE_CONTENT_BANK === $context ) {
281 + $contents = array_filter(
282 + $contents,
283 + fn( $content ) => tutor()->course_post_type === $content['key']
284 + );
285 + $contents = array_values( $contents ); // Reset keys.
286 + }
287 + return apply_filters( 'tutor_pro_exportable_contents', $contents );
288 + }
289 +
290 + /**
291 + * Get exportable sub types.
292 + *
293 + * @since 3.6.0
294 + *
295 + * @return array
296 + */
297 + public function get_exportable_sub_contents(): array {
298 + $types = array(
299 + tutor()->quiz_post_type => __( 'Quizzes', 'tutor-pro' ),
300 + tutor()->assignment_post_type => __( 'Assignments', 'tutor-pro' ),
301 + );
302 +
303 + $types = array(
304 + array(
305 + 'label' => __( 'Questions', 'tutor-pro' ),
306 + 'key' => self::TYPE_QUESTIONS,
307 + ),
308 + array(
309 + 'label' => __( 'Lessons', 'tutor-pro' ),
310 + 'key' => tutor()->lesson_post_type,
311 + ),
312 + array(
313 + 'label' => __( 'Quizzes', 'tutor-pro' ),
314 + 'key' => tutor()->quiz_post_type,
315 + ),
316 + array(
317 + 'label' => __( 'Assignments', 'tutor-pro' ),
318 + 'key' => tutor()->assignment_post_type,
319 + ),
320 + );
321 +
322 + if ( ! tutor_utils()->is_addon_enabled( 'tutor-assignments' ) ) {
323 + unset( $types[2] );
324 + }
325 +
326 + return apply_filters( 'tutor_pro_exportable_sub_types', $types );
327 + }
328 +
329 + /**
330 + * Add courses to export
331 + *
332 + * @since 3.6.0
333 + *
334 + * @since 3.8.1 added $current_sub_file parameter
335 + *
336 + * @param string|array $course_ids Course IDs, comma separate or array.
337 + * @param string|array $content_types A single type or array of types to export.
338 + * @param string $current_sub_file The sub-file type currently being processed (e.g., course, enrollments, plans).
339 + *
340 + * @return $this object
341 + */
342 + public function add_courses( $course_ids, $content_types, $current_sub_file ) {
343 + if ( is_string( $content_types ) ) {
344 + $content_types = array( $content_types );
345 + }
346 +
347 + $this->course_ids = $this->prepare_content_ids( $course_ids );
348 + $this->content_types = $content_types;
349 + $this->current_sub_file = $current_sub_file;
350 + return $this;
351 + }
352 +
353 + /**
354 + * Add bundles to export
355 + *
356 + * @since 3.6.0
357 + *
358 + * @since 3.8.1 added $current_sub_file parameter
359 + *
360 + * @param string|array $bundle_ids Bundle IDs comma separate or array.
361 + * @param string $current_sub_file The sub-file type currently being processed (e.g., course, enrollments, plans).
362 + *
363 + * @return $this object
364 + */
365 + public function add_bundles( $bundle_ids, $current_sub_file ) {
366 + $this->bundle_ids = $this->prepare_content_ids( $bundle_ids );
367 + $this->current_sub_file = $current_sub_file;
368 + return $this;
369 + }
370 +
371 + /**
372 + * Add collection to export
373 + *
374 + * @since 3.7.0
375 + *
376 + * @param string|array $collection_ids Collection IDs comma separate or array.
377 + *
378 + * @return $this object
379 + */
380 + public function add_collections( $collection_ids ) {
381 + $this->collection_ids = $this->prepare_content_ids( $collection_ids );
382 + return $this;
383 + }
384 +
385 + /**
386 + * Add bundles to export
387 + *
388 + * @since 3.6.0
389 + *
390 + * @return $this object
391 + */
392 + public function add_settings() {
393 + $this->export_settings = true;
394 + return $this;
395 + }
396 +
397 + /**
398 + * Mark grade book settings as added.
399 + *
400 + * @since 3.8.1
401 + *
402 + * @return $this Returns the current instance for method chaining.
403 + */
404 + public function add_grade_book_settings() {
405 + $this->grade_book_settings = true;
406 + return $this;
407 + }
408 +
409 + /**
410 + * Add media files to export
411 + *
412 + * @since 3.6.0
413 + *
414 + * @return $this object
415 + */
416 + public function add_media_files() {
417 + $this->keep_media_files = true;
418 + return $this;
419 + }
420 +
421 + /**
422 + * Add user data to export
423 + *
424 + * @since 3.8.1
425 + *
426 + * @return $this object
427 + */
428 + public function add_user_data() {
429 + $this->keep_user_data = true;
430 + return $this;
431 + }
432 +
433 + /**
434 + * Export new export
435 + *
436 + * @throws \Throwable If invalid course id bundle id detect.
437 + *
438 + * @since 3.6.0
439 + */
440 + public function export() {
441 + $export = array(
442 + 'schema_version' => self::SCHEMA_VERSION,
443 + 'exported_at' => current_time( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ) ),
444 + 'keep_media_files' => $this->keep_media_files,
445 + 'keep_user_data' => $this->keep_user_data,
446 + 'data' => array(),
447 + );
448 +
449 + if ( count( $this->course_ids ) ) {
450 + $course_data = array(
451 + 'content_type' => tutor()->course_post_type,
452 + 'data' => array(),
453 + );
454 +
455 + foreach ( $this->course_ids as $id ) {
456 + try {
457 + $course_data['data'] = $this->export_courses( $id );
458 + } catch ( \Throwable $th ) {
459 + throw $th;
460 + }
461 + }
462 +
463 + $export['data'][] = $course_data;
464 + }
465 +
466 + if ( count( $this->bundle_ids ) ) {
467 + $bundle_data = array(
468 + 'content_type' => tutor()->bundle_post_type,
469 + 'data' => array(),
470 + );
471 +
472 + if ( tutor_utils()->is_addon_enabled( 'course-bundle' ) ) {
473 + foreach ( $this->bundle_ids as $id ) {
474 + try {
475 + $bundle_data['data'] = $this->export_bundles( $id );
476 + } catch ( \Throwable $th ) {
477 + throw $th;
478 + }
479 + }
480 + }
481 +
482 + $export['data'][] = $bundle_data;
483 + }
484 +
485 + if ( count( $this->collection_ids ) ) {
486 + $collection_data = array(
487 + 'content_type' => CollectionModel::POST_TYPE,
488 + 'data' => array(),
489 + );
490 +
491 + foreach ( $this->collection_ids as $id ) {
492 + try {
493 + $export_data = CollectionExporter::export( $id, $this->keep_media_files );
494 + $collection_data['data'][] = $export_data;
495 + } catch ( \Throwable $th ) {
496 + throw $th;
497 + }
498 + }
499 +
500 + $export['data'][] = $collection_data;
501 + }
502 +
503 + if ( $this->export_settings ) {
504 + $settings = array(
505 + 'content_type' => self::TYPE_SETTINGS,
506 + 'data' => get_option( 'tutor_option' ),
507 + );
508 +
509 + $export['data'][] = $settings;
510 + }
511 +
512 + if ( count( $this->membership_plan_ids ) ) {
513 +
514 + $membership_plan_data = array(
515 + 'content_type' => self::TYPE_MEMBERSHIP_PLANS,
516 + 'data' => array(),
517 + );
518 +
519 + foreach ( $this->membership_plan_ids as $id ) {
520 + try {
521 + $export_data = self::export_membership_plans( $id );
522 + $membership_plan_data['data'] = $export_data;
523 + } catch ( \Throwable $th ) {
524 + throw $th;
525 + }
526 + }
527 +
528 + $export['data'][] = $membership_plan_data;
529 + }
530 +
531 + if ( $this->grade_book_settings ) {
532 + $grade_book_settings = array(
533 + 'content_type' => self::GRADE_BOOKS_SETTINGS,
534 + 'data' => get_gradebook_settings(),
535 + );
536 +
537 + $export['data'][] = $grade_book_settings;
538 + }
539 +
540 + return $export;
541 + }
542 +
543 + /**
544 + * Convert comma separated id to array id
545 + *
546 + * @since 3.6.0
547 + *
548 + * @param mixed $ids Content ids String|array.
549 + *
550 + * @return array
551 + */
552 + private function prepare_content_ids( $ids ): array {
553 + return array_map( 'intval', is_array( $ids ) ? $ids : explode( ',', $ids ) );
554 + }
555 +
556 + /**
557 + * Get default exporter schema
558 + *
559 + * @since 3.6.0
560 + *
561 + * @return array
562 + */
563 + public function get_schema() {
564 + $export = array(
565 + 'schema_version' => self::SCHEMA_VERSION,
566 + 'exported_at' => current_time( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ) ),
567 + 'keep_media_files' => $this->keep_media_files,
568 + 'keep_user_data' => $this->keep_user_data,
569 + 'data' => array(),
570 + );
571 +
572 + return $export;
573 + }
574 +
575 + /**
576 + * Set membership plan IDs for the current object.
577 + *
578 + * @since 3.8.1
579 + *
580 + * @param array|int $membership_plan_ids Single ID or an array of membership plan IDs to add.
581 + * @param string $current_sub_file Set Current Sub File to export.
582 + *
583 + * @return $this Returns the current instance for method chaining.
584 + */
585 + public function add_membership_plans( $membership_plan_ids, $current_sub_file ) {
586 + $this->membership_plan_ids = $this->prepare_content_ids( $membership_plan_ids );
587 + $this->current_sub_file = $current_sub_file;
588 + return $this;
589 + }
590 +
591 + /**
592 + * Set the job ID for the current instance.
593 + *
594 + * @param int $job_id The ID of the job to associate with this instance.
595 + * @return void
596 + */
597 + public function add_job_id( $job_id ) {
598 + $this->job_id = $job_id;
599 + }
600 +
601 + /**
602 + * Export course-related data for a given course ID based on the current sub-file type.
603 + *
604 + * @since 3.8.0
605 + *
606 + * @param int $id The ID of the course to export.
607 + *
608 + * @return array An associative array with the sub-file type as the key
609 + * and the exported data as the value.
610 + */
611 + private function export_courses( $id ): array {
612 +
613 + switch ( $this->current_sub_file ) {
614 +
615 + case self::COURSE:
616 + return array(
617 + self::COURSE => empty( $id ) ? array() : CourseExporter::export( $id, $this->content_types, $this->keep_media_files ),
618 + );
619 +
620 + case self::ENROLLMENTS:
621 + $enrollment_data = EnrollmentExporter::export( $id );
622 +
623 + // Update Membership Plan IDs.
624 + if ( ! empty( $enrollment_data['plan_ids'] ) ) {
625 + $this->update_job_data( $enrollment_data['plan_ids'] );
626 + }
627 +
628 + return array(
629 + self::ENROLLMENTS => $enrollment_data['enrollment_data'],
630 + );
631 +
632 + case self::PLANS:
633 + $export_data = PlanExporter::export( $id, self::COURSE );
634 + $plan_ids = PlanExporter::extract_plan_ids( $export_data );
635 + $course_and_plan_ids = array(
636 + 'plan_ids' => $plan_ids,
637 + 'course_id' => $id,
638 + );
639 +
640 + update_option( self::OPT_NAME . $this->job_id . '_course_and_plan_ids', $course_and_plan_ids );
641 +
642 + return array( self::PLANS => $export_data );
643 +
644 + case self::ORDERS:
645 + $course_and_plan_ids = get_option( self::OPT_NAME . $this->job_id . '_course_and_plan_ids' );
646 + $course_and_plan_ids = array_merge( $course_and_plan_ids['plan_ids'] ?? array(), array( $course_and_plan_ids['course_id'] ?? $id ) );
647 +
648 + $export_data = OrderExporter::export( $course_and_plan_ids, $id );
649 +
650 + delete_option( self::OPT_NAME . $this->job_id . '_course_and_plan_ids' );
651 +
652 + return array( self::ORDERS => $export_data );
653 +
654 + case self::SUBSCRIPTIONS:
655 + $course_and_plan_ids = get_option( self::OPT_NAME . $this->job_id . '_course_and_plan_ids' );
656 + $plan_ids = $course_and_plan_ids['plan_ids'];
657 +
658 + return array( self::SUBSCRIPTIONS => SubscriptionExporter::export( $plan_ids ) );
659 +
660 + case self::PROGRESS:
661 + return array( self::PROGRESS => ProgressExporter::export( $id ) );
662 +
663 + case self::REVIEWS:
664 + return array( self::REVIEWS => ( new Reviews() )->get_reviews_by_course_id( $id ) );
665 +
666 + default:
667 + return array();
668 + }
669 + }
670 +
671 + /**
672 + * Export bundle data based on the current sub file type.
673 + *
674 + * @since 3.8.1
675 + *
676 + * @param int $id Bundle ID to export.
677 + *
678 + * @return array Exported data keyed by sub file type.
679 + */
680 + private function export_bundles( $id ) {
681 +
682 + switch ( $this->current_sub_file ) {
683 +
684 + case self::BUNDLE:
685 + return array(
686 + self::BUNDLE => BundleExporter::export( $id ),
687 + );
688 +
689 + case self::ENROLLMENTS:
690 + return array(
691 + self::ENROLLMENTS => EnrollmentExporter::export( $id, true )['enrollment_data'],
692 + );
693 +
694 + case self::PLANS:
695 + $export_data = PlanExporter::export( $id, self::BUNDLE );
696 + $plan_ids = PlanExporter::extract_plan_ids( $export_data );
697 + $course_and_plan_ids = array(
698 + 'plan_ids' => $plan_ids,
699 + 'course_id' => $id,
700 + );
701 +
702 + update_option( self::OPT_NAME . $this->job_id . '_course_and_plan_ids', $course_and_plan_ids );
703 +
704 + return array( self::PLANS => $export_data );
705 +
706 + case self::ORDERS:
707 + $course_and_plan_ids = get_option( self::OPT_NAME . $this->job_id . '_course_and_plan_ids' );
708 +
709 + $course_and_plan_ids = array_merge( $course_and_plan_ids['plan_ids'] ?? array(), array( $course_and_plan_ids['course_id'] ?? $id ) );
710 +
711 + $export_data = OrderExporter::export( $course_and_plan_ids, $id );
712 +
713 + delete_option( self::OPT_NAME . $this->job_id . '_course_and_plan_ids' );
714 +
715 + return array( self::ORDERS => $export_data );
716 +
717 + case self::SUBSCRIPTIONS:
718 + $course_and_plan_ids = get_option( self::OPT_NAME . $this->job_id . '_course_and_plan_ids' );
719 + $plan_ids = $course_and_plan_ids['plan_ids'];
720 +
721 + return array( self::SUBSCRIPTIONS => SubscriptionExporter::export( $plan_ids ) );
722 +
723 + case self::COURSES:
724 + $this->content_types = BundleExporter::get_content_types();
725 + $this->current_sub_file = $this->current_course_sub_file;
726 + $export_data = $this->export_courses( $this->current_bundle_course_id );
727 +
728 + return array( self::COURSES => $export_data );
729 +
730 + default:
731 + return array();
732 + }
733 + }
734 +
735 + /**
736 + * Set the current bundle course ID.
737 + *
738 + * @since 3.8.1
739 + *
740 + * @param int $id Bundle course ID.
741 + *
742 + * @return void
743 + */
744 + public function set_current_bundle_course_id( $id ) {
745 +
746 + $this->current_bundle_course_id = $id;
747 + }
748 +
749 + /**
750 + * Set the current course sub file.
751 + *
752 + * @since 3.8.1
753 + *
754 + * @param string $id Current course sub file key.
755 + *
756 + * @return void
757 + */
758 + public function set_current_course_sub_file( $id ) {
759 + $this->current_course_sub_file = $id;
760 + }
761 +
762 + /**
763 + * Export membership plan data based on the current sub file type.
764 + *
765 + * @since 3.8.1
766 + *
767 + * @param int $id Membership plan ID to export.
768 + *
769 + * @return array Exported data keyed by sub file type.
770 + */
771 + private function export_membership_plans( $id ) {
772 +
773 + switch ( $this->current_sub_file ) {
774 +
775 + case self::PLANS:
776 + return array( self::PLANS => PlanExporter::export( $id ) );
777 +
778 + case self::SUBSCRIPTIONS:
779 + return array( self::SUBSCRIPTIONS => SubscriptionExporter::export( array( $id ) ) );
780 +
781 + case self::ORDERS:
782 + return array( self::ORDERS => OrderExporter::export( array( $id ) ) );
783 +
784 + default:
785 + return array();
786 + }
787 + }
788 +
789 + /**
790 + * Set the job data reference for the exporter.
791 + *
792 + * @since 3.8.1
793 + *
794 + * @param array $job_data Reference to the job data array.
795 + */
796 + public function set_job_data( &$job_data ) {
797 +
798 + if ( $this->keep_user_data ) {
799 + $this->job_data = &$job_data;
800 + return $this;
801 + }
802 + }
803 +
804 +
805 + /**
806 + * Update job requirements with additional membership plan IDs.
807 + *
808 + * @since 3.8.1
809 + *
810 + * @param int[] $plan_ids Array of membership plan IDs to add to job requirements.
811 + * @return void
812 + */
813 + private function update_job_data( $plan_ids ) {
814 +
815 + if ( ! empty( $plan_ids ) ) {
816 +
817 + foreach ( $this->job_data['job_requirements'] as &$job ) {
818 +
819 + if ( self::TYPE_MEMBERSHIP_PLANS === $job['type'] ) {
820 + $job['ids'] = array_unique( array_merge( $job['ids'], $plan_ids ) );
821 + }
822 + }
823 + }
824 + }
825 +
826 + /**
827 + * Append additional export items to the provided contents array.
828 + *
829 + * @since 3.8.1
830 + *
831 + * @param array $contents Existing export contents.
832 + * @return array Modified export contents including the additional items.
833 + */
834 + public function append_export_contents( array $contents ) {
835 + if ( empty( $contents ) ) {
836 + return $contents;
837 + }
838 +
839 + if ( tutor_utils()->is_addon_enabled( 'subscription' ) ) {
840 + $contents[] = array(
841 + 'type' => self::TYPE_MEMBERSHIP_PLANS,
842 + 'ids' => array(),
843 + );
844 + }
845 +
846 + if ( tutor_utils()->is_addon_enabled( TUTOR_GB()->basename ) ) {
847 + $contents[] = array(
848 + 'type' => self::GRADE_BOOKS_SETTINGS,
849 + );
850 + }
851 +
852 + return $contents;
853 + }
854 + }
855 +