0 ) { $sql = $sql->add( SqlPart::of( ' AND org_id = %d', $org_id ) ); } $courses = array_map( 'intval', Db::col( $sql ) ); if ( null !== $only_course_ids ) { $courses = array_values( array_intersect( $courses, CourseRepository::ids( $only_course_ids ) ) ); } return $this->for_courses( $user_id, $courses, $lang ); } public function for_courses( int $user_id, array $course_ids, string $lang, bool $with_items = true ): array { $course_ids = array_keys( Services::course_repo()->get_many( CourseRepository::ids( $course_ids ) ) ); if ( array() === $course_ids ) { return array(); } $titles = Services::posts()->titles( ObjectType::COURSE, $course_ids, $lang ); $keys = $this->sort_keys( $course_ids, $titles ); usort( $course_ids, static fn( int $a, int $b ): int => $keys[ $a ] <=> $keys[ $b ] ); $hidden = $with_items ? Services::programme_gate()->hidden_items_many( $user_id, $course_ids ) : array(); $out = array(); foreach ( $course_ids as $course_id ) { $out[] = array( 'course_id' => $course_id, 'title' => $titles[ $course_id ]['title'] ?? '', 'url' => Urls::course_url( $course_id, $lang ), 'items' => $with_items ? $this->items( $course_id, $hidden[ $course_id ] ?? array(), $lang ) : array(), ); } return $out; } private function items( int $course_id, array $hidden, string $lang ): array { $items = array(); foreach ( Services::curriculum_repo()->outline( $course_id )->items as $item ) { if ( ! in_array( $item->id, $hidden, true ) ) { $items[] = $item; } } if ( array() === $items ) { return array(); } $units = Services::unit_repo()->get_many( array_map( static fn( $i ): int => $i->unit_id, $items ) ); $content = true; foreach ( $items as $item ) { $unit = $units[ $item->unit_id ] ?? null; $content = $content && null !== $unit && $unit->type->is_content_controlled(); } if ( $content ) { return array(); } $titles = Services::posts()->titles( ObjectType::UNIT, array_map( static fn( $i ): int => $i->unit_id, $items ), $lang ); $out = array(); foreach ( $items as $item ) { $out[] = array( 'title' => $titles[ $item->unit_id ]['title'] ?? '', 'url' => Urls::item_url( $course_id, $item->id, $lang ), ); } return $out; } private function sort_keys( array $course_ids, array $titles ): array { $filings = Services::category_repo()->filings( ObjectType::COURSE, $course_ids ); $first = array(); foreach ( $filings as $course_id => $categories ) { if ( array() !== $categories ) { $first[ $course_id ] = (int) $categories[0]; } } $ranks = array(); $positions = array(); if ( array() !== $first ) { foreach ( Services::category_repo()->get_many( array_values( array_unique( $first ) ) ) as $id => $category ) { $ranks[ $id ] = $category->tree_rank; } foreach ( Db::rows( 'SELECT category_id, object_id, position FROM %i WHERE object_type = %d AND object_id IN (' . implode( ',', array_fill( 0, count( $first ), '%d' ) ) . ')', array_merge( array( Db::table( 'category_objects' ), ObjectType::COURSE->value ), array_keys( $first ) ) ) as $row ) { if ( ( $first[ (int) $row['object_id'] ] ?? 0 ) === (int) $row['category_id'] ) { $positions[ (int) $row['object_id'] ] = (int) $row['position']; } } } $keys = array(); foreach ( $course_ids as $course_id ) { $category = $first[ $course_id ] ?? 0; $position = $positions[ $course_id ] ?? 0; $keys[ $course_id ] = array( $category > 0 ? ( $ranks[ $category ] ?? PHP_INT_MAX - 1 ) : PHP_INT_MAX, $position > 0 ? $position : PHP_INT_MAX, Fold::fold( $titles[ $course_id ]['title'] ?? '' ), $course_id, ); } return $keys; } }