From 78eb0e78cf78892098cd5ca24979f195722ccc08 Mon Sep 17 00:00:00 2001 From: Maxim Beder Date: Mon, 25 Sep 2023 11:20:56 +0200 Subject: [PATCH] feat: set course for wiki based on the wiki_slug Learners want to have the usual course navigation when viewing a wiki, so that they can go back to the course related to the wiki and browse other tabs/sections of the course. Wiki reads the course from the `request.course`. If it's not present, i.e. None or not set on the request, it will not show the course navigation UI. It seems like `WikiAccessMiddleware` already has the code that parses course id from the request (when the request is for a wiki view) and sets the course for the request. However, it doesn't work in most scenarios, because the course id is not in the it's normal format in most requests that go to wiki. For example, when a leaner clicks on a wiki tab from the course overview, they are redirected to `/wiki//` path. The wiki slug is taken from course's `wiki_slug` field. This slug can be used to figure out what course this wiki belongs to in most (not all) cases. This commit adds code to the `WikiAccessMiddleware` that attempts to find a course based on wiki slug, and in case of success, sets the course to the `request.course`, so that wiki can display course navigation UI. --- lms/djangoapps/course_wiki/middleware.py | 17 +++++++++++++++++ .../course_wiki/tests/test_middleware.py | 7 +++++++ 2 files changed, 24 insertions(+) diff --git a/lms/djangoapps/course_wiki/middleware.py b/lms/djangoapps/course_wiki/middleware.py index 54884a23f252..6d32604d841f 100644 --- a/lms/djangoapps/course_wiki/middleware.py +++ b/lms/djangoapps/course_wiki/middleware.py @@ -15,6 +15,8 @@ from openedx.features.enterprise_support.api import get_enterprise_consent_url from common.djangoapps.student.models import CourseEnrollment +from xmodule import modulestore + class WikiAccessMiddleware(MiddlewareMixin): """ @@ -55,6 +57,21 @@ def process_view(self, request, view_func, view_args, view_kwargs): # lint-amne course_id = course_id_from_url(request.path) wiki_path = request.path.partition('/wiki/')[2] + # if no wiki_path, can't get wiki_slug, so no point trying to look up + # course_id by wiki_slug + if not course_id and wiki_path: + # wiki path always starts with wiki_slug + wiki_slug = wiki_path.split('/')[0] + + modstore = modulestore.django.modulestore() + course_ids = modstore.get_courses_for_wiki(wiki_slug) + # the above can return multiple courses, and to avoid ambiguity and + # avoid pointing to wrong courses, we only set course_id if we've + # got an exact match, i.e. only one course was returned for a + # wiki_slug + if len(course_ids) == 1: + course_id = course_ids[0] + if course_id: # This is a /courses/org/name/run/wiki request course_path = f"/courses/{str(course_id)}" diff --git a/lms/djangoapps/course_wiki/tests/test_middleware.py b/lms/djangoapps/course_wiki/tests/test_middleware.py index 16937cc77289..38bcf5bb1e43 100644 --- a/lms/djangoapps/course_wiki/tests/test_middleware.py +++ b/lms/djangoapps/course_wiki/tests/test_middleware.py @@ -34,3 +34,10 @@ def test_url_tranform(self): response = self.client.get('/courses/edx/math101/2014/wiki/math101/') self.assertContains(response, '/courses/edx/math101/2014/wiki/math101/_edit/') self.assertContains(response, '/courses/edx/math101/2014/wiki/math101/_settings/') + + def test_finds_course_by_wiki_slug(self): + """Test that finds course by wiki slug, if course id is not present in the url.""" + response = self.client.get('/wiki/math101/') + request = response.wsgi_request + self.assertTrue(hasattr(request, 'course')) + self.assertEqual(request.course.id, self.course_math101.id)