Looking at get_courses_search() (HEAD), with the above example in mind:
$totalcount = count_records_sql('SELECT COUNT(*) FROM '. $selectsql);--> $totalcount = 19
Then
$courses = get_records_sql('SELECT * FROM '. $selectsql .' ORDER BY '. $sort, $page, $recordsperpage);retrieves the first ten matching courses. We have 5 of these an hidden, 5 visible.
Then
foreach ($courses as $key => $course) { if (!$course->visible) { if (!has_capability('moodle/course:viewhiddencourses', get_context_instance(CONTEXT_COURSE, $course->id))) { unset($courses[$key]); $totalcount--; } } }reduces the total by 5, leaving the total to 14, we only get 5 courses on that page. Clicking to the next page has similar issues: it retrieves records but doesn't care for the hidden/visible factor, sometimes leaving some courses "in the dark" completely.
My initial fix was to retrieve only the id and visible columns for all of the courses matching the search criteria, then weeding hidden (or adding visible) courses, resulting in a list of course ids that we want. Then with an array_splice and "id IN" query I fetch the wanted page.
Problem: The "is this course hidden" generates several DB queries, so checking for all of the potential courses fir visibility, just to show a pageful, generates unnecessary queries.
Problem: Without going though all of the courses the total count might always be incorrect.
I tried to be more clever about this, just querying, say 2 x $recordsperpage, then weeding hidden courses, checking if we are left with a full page. If yes, ok, if not, fetch another bunch. Problem: "skipping" over pagefuls of hidden courses still generates many queries + the total count could still be wrong.
Any thoughts? Caching the course visibility per user? (arf...) I couldn't figure out a way to include the hidden/visible criteria to the course search query directly, because it's not a binary issue until some calculations and more checking...