'sequencing' ); public const DEFAULT_TAB = 'curriculum'; public const KEY_PATTERN = '/^[a-z][a-z0-9_-]{0,31}$/'; public const SETTINGS_SECTIONS = array( 'main', 'texts', 'access', 'prerequisites', 'files', 'certificate', 'page', 'staff', 'links', 'live' ); public static function keys(): array { $keys = apply_filters( 'rooster_lms_course_builder_tabs', self::FREE ); $out = array(); foreach ( is_array( $keys ) ? $keys : array() as $key ) { if ( is_string( $key ) && 1 === preg_match( self::KEY_PATTERN, $key ) && ! in_array( $key, $out, true ) ) { $out[] = $key; } } return array() === $out ? self::FREE : $out; } public static function exists( string $tab ): bool { return in_array( $tab, self::keys(), true ); } public static function canonical( string $tab ): string { $tab = self::ALIASES[ $tab ] ?? $tab; return self::exists( $tab ) ? $tab : ''; } public static function read( Course $course, string $tab, string $lang, int $user_id ): array { $data = match ( $tab ) { 'curriculum' => self::curriculum( $course, $lang ), 'sequencing' => self::sequencing( $course, $lang ), 'settings' => self::settings( $course, $lang ), 'faq' => CommunityTabs::faq( $course, $lang, $user_id ), 'notice' => CommunityTabs::notice( $course, $lang ), 'reviews' => CommunityTabs::reviews( $course ), 'qa' => CommunityTabs::qa( $course ), default => array(), }; $data = apply_filters( 'rooster_lms_course_builder_tab_data', $data, $tab, $course, $lang, $user_id ); $data = is_array( $data ) ? $data : array(); $rev = is_string( $data['rev'] ?? null ) && 1 === preg_match( Rev::ANY, $data['rev'] ) ? $data['rev'] : Rev::of( $data ); return array( 'tab' => $tab, 'rev' => $rev, 'data' => $data, ); } public static function text_lang( string $lang ): string { return Strings::writes_stored( $lang ) ? '' : Strings::edit_language( $lang ); } private static function view( string $lang ): string { return Strings::edit_language( $lang ); } private static function curriculum( Course $course, string $lang ): array { return CurriculumController::shape( $course->id, self::text_lang( $lang ) ); } private static function sequencing( Course $course, string $lang ): array { $outline = CurriculumController::shape( $course->id, self::text_lang( $lang ) ); $items = Services::curriculum_repo()->items( array_map( static fn( array $i ): int => (int) $i['id'], $outline['items'] ) ); $out = array(); foreach ( $outline['items'] as $row ) { $item = $items[ (int) $row['id'] ] ?? null; $out[] = array( 'id' => (int) $row['id'], 'title' => $row['title'], 'type' => $row['type'], 'section_id' => $row['section_id'], 'unlock' => null === $item ? 'none' : strtolower( $item->rules->unlock->name ), 'days' => $item?->rules->days, 'at' => $item?->rules->at, ); } return array( 'sequential' => $course->sequential, 'sections' => $outline['sections'], 'items' => $out, ); } private static function settings( Course $course, string $lang ): array { $view = self::view( $lang ); $details = Services::course_details(); $files = Services::course_files()->for_course( $course->id ); $titles = array() === $files ? array() : Services::course_files()->titles( $files, $view ); $choices = array(); foreach ( array( 'levels' => Services::course_levels(), 'badges' => Services::course_badges(), ) as $key => $service ) { $active = $service->active(); $labels = $service->labels( $active, $view ); $choices[ $key ] = array_map( static fn( $item ): array => array( 'id' => $item->id, 'label' => (string) ( $labels[ $item->id ] ?? $item->slug ), ), $active ); } return array( 'sections' => self::SETTINGS_SECTIONS, 'course' => array( 'visibility' => $course->visibility->slug(), 'enrol_policy' => $course->enrol_policy->slug(), 'completion_rule' => strtolower( $course->completion_rule->name ), 'completion_percent' => $course->completion_percent, 'sequential' => $course->sequential, 'validity_days' => $course->validity_days, 'certificate_tpl_id' => $course->certificate_tpl_id, 'delivery' => $course->delivery->slug(), 'capacity' => $course->capacity, 'attendance_required' => $course->attendance_required, 'qa_mode' => $course->qa_mode, 'reviews_mode' => $course->reviews_mode, 'grade_scale_id' => $course->grade_scale_id, ), 'details' => $details->shape( $course, $view ), 'texts' => (object) $details->texts_in( $course->id, $view ), 'points' => (object) $details->points_in( $course->id, $view ), 'files' => array_map( static fn( CourseFile $f ): array => array( 'id' => $f->id, 'title' => (string) ( $titles[ $f->id ] ?? $f->title ), 'file' => $f->is_file(), 'url' => $f->is_file() ? '' : $f->url, 'access' => $f->access->slug(), ), $files ), 'choices' => $choices, ); } }