diff --git a/app/controllers/admin/courses.php b/app/controllers/admin/courses.php index b28a0fe1983b3cc30bef18568a1f5a1cdc194101..d0e2d5331a1f8fba16498410686aff5bb3d4b6c3 100644 --- a/app/controllers/admin/courses.php +++ b/app/controllers/admin/courses.php @@ -375,14 +375,14 @@ class Admin_CoursesController extends AuthenticatedController } PluginEngine::sendMessage(AdminCourseWidgetPlugin::class, 'applyFilters', $filter); - $count = $filter->countCourses(); - if ($count > $this->max_show_courses && !Request::submitted('without_limit')) { - $this->render_json([ - 'count' => $count - ]); + try { + $courses = $filter->fetchCourses( + Request::bool('without_limit') ? null: $this->max_show_courses + ); + } catch (OverflowException $e) { + $this->render_json(['count' => (int) $e->getMessage()]); return; } - $courses = AdminCourseFilter::get()->getCourses(); $data = [ 'data' => [] diff --git a/lib/classes/AdminCourseFilter.class.php b/lib/classes/AdminCourseFilter.class.php index da8ce54f7e055ad8771f3d79e7c8bda739fd9087..3b9cb4ba6a2894e3326cd75c98795cafe54f70cd 100644 --- a/lib/classes/AdminCourseFilter.class.php +++ b/lib/classes/AdminCourseFilter.class.php @@ -28,6 +28,8 @@ class AdminCourseFilter { static protected $instance = null; + + /** @var SQLQuery|null */ public $query = null; public $max_show_courses = 500; public $settings = []; @@ -109,13 +111,10 @@ class AdminCourseFilter } if (Config::get()->ALLOW_ADMIN_RELATED_INST) { - $sem_inst = 'seminar_inst'; - $this->query->join('seminar_inst', 'seminar_inst', 'seminar_inst.seminar_id = seminare.Seminar_id'); + $this->query->where('seminar_inst', 'EXISTS (SELECT 1 FROM seminar_inst WHERE seminar_id = seminare.Seminar_id AND institut_id IN (:institut_ids))'); } else { - $sem_inst = 'seminare'; + $this->query->where("seminar_inst", "seminare.institut_id IN (:institut_ids)"); } - - $this->query->where('seminar_inst', "$sem_inst.institut_id IN (:institut_ids)"); $this->query->parameter('institut_ids', $inst_ids); if ($GLOBALS['user']->cfg->MY_COURSES_SELECTED_CYCLE) { @@ -195,6 +194,16 @@ class AdminCourseFilter return $this->query->count(); } + /** + * @param int|null $limit + * @return Course[] + */ + public function fetchCourses(?int $limit = null): array + { + NotificationCenter::postNotification('AdminCourseFilterWillQuery', $this); + return $this->query->fetchAll(Course::class, $limit); + } + /** * Returns the data of the resultset of the AdminCourseFilter. * @@ -206,16 +215,16 @@ class AdminCourseFilter */ public function getCoursesForAdminWidget(string $order_by = 'name') { - $count_courses = $this->countCourses(); - $order = 'seminare.name'; - if ($order_by === 'number') { - $order = 'seminare.veranstaltungsnummer, seminare.name'; - } - if ($count_courses && $count_courses <= $this->max_show_courses) { + try { + $order = 'seminare.name'; + if ($order_by === 'number') { + $order = 'seminare.veranstaltungsnummer, seminare.name'; + } $this->query->orderBy($order); - return $this->getCourses(); + return $this->fetchCourses($this->max_show_courses); + } catch (OverflowException $e) { + return []; } - return []; } } diff --git a/lib/classes/SQLQuery.php b/lib/classes/SQLQuery.php index 0442604ff6e2933bd411c9c5e8ac58e56254234c..6c8f49ec7d3a1ba1577d3324215297fcc61db568 100644 --- a/lib/classes/SQLQuery.php +++ b/lib/classes/SQLQuery.php @@ -215,14 +215,22 @@ class SQLQuery /** * Fetches the whole resultset as an array of associative arrays. If you define * a sorm_class the result will be an array of the sorm-objects. - * @param $sorm_class_or_column : column name, a class of SimpleORMap or null for associative array. - * @return array of arrays or array of objects or array of values. + * + * @template T of SimpleORMap + * @param class-string<T>|string|null $sorm_class_or_column : column name, a class of SimpleORMap or null for associative array. + * @param int|null $max_results Maximum number of results to return + * @return array[]|T[]|mixed[] arrays or array of objects or array of values. + * + * @throws OverflowException if number of found rows is greater than $max_results */ - public function fetchAll($sorm_class_or_column = null) + public function fetchAll($sorm_class_or_column = null, ?int $max_results = null) { NotificationCenter::postNotification('SQLQueryWillExecute', $this); - if (is_string($sorm_class_or_column) && !is_subclass_of($sorm_class_or_column, "SimpleORMap")) { + if ( + is_string($sorm_class_or_column) + && !is_subclass_of($sorm_class_or_column, SimpleORMap::class) + ) { $sql = "SELECT `{$this->settings['table']}`.`{$sorm_class_or_column}` "; } else { $sql = "SELECT `{$this->settings['table']}`.* "; @@ -239,16 +247,31 @@ class SQLQuery NotificationCenter::postNotification('SQLQueryDidExecute', $this); - if (is_string($sorm_class_or_column) && !is_subclass_of($sorm_class_or_column, "SimpleORMap")) { - return $statement->fetchAll(PDO::FETCH_COLUMN, 0); + if ( + is_string($sorm_class_or_column) + && !is_subclass_of($sorm_class_or_column, SimpleORMap::class) + ) { + return $statement->fetchAll(PDO::FETCH_COLUMN); } - $alldata = $statement->fetchAll(PDO::FETCH_ASSOC); - if (!$sorm_class_or_column) { - return $alldata; + $statement->setFetchMode(PDO::FETCH_ASSOC); + + $result = []; + $count = 0; + foreach ($statement as $row) { + $result[$count++] = $sorm_class_or_column ? $sorm_class_or_column::buildExisting($row) : $row; + + if ($max_results && $count > $max_results) { + // Count remaining rows + $statement->setFetchMode(PDO::FETCH_COLUMN, 0); + while ($statement->fetch()) { + $count += 1; + } + throw new OverflowException($count); + } } - return array_map("{$sorm_class_or_column}::buildExisting", $alldata); + return $result; } /**