diff --git a/lms/djangoapps/courseware/tests/test_video_mongo.py b/lms/djangoapps/courseware/tests/test_video_mongo.py index 620cad897086..753eb2e5d462 100644 --- a/lms/djangoapps/courseware/tests/test_video_mongo.py +++ b/lms/djangoapps/courseware/tests/test_video_mongo.py @@ -1201,7 +1201,9 @@ def test_get_html_on_toggling_hls_feature(self, hls_feature_enabled, expected_va 'youtube': 'https://yt.com/?v=v0TFmdO4ZP0', 'desktop_mp4': 'https://mp4.com/dm.mp4' } - with patch('xmodule.video_block.video_block.HLSPlaybackEnabledFlag.feature_enabled') as feature_enabled: + with patch( + 'openedx.core.djangoapps.video_config.services.VideoConfigService.is_hls_playback_enabled' + ) as feature_enabled: feature_enabled.return_value = hls_feature_enabled video_xml = '' self.initialize_block(data=video_xml) @@ -1211,7 +1213,10 @@ def test_get_html_on_toggling_hls_feature(self, hls_feature_enabled, expected_va expected_val_profiles, ) - @patch('xmodule.video_block.video_block.HLSPlaybackEnabledFlag.feature_enabled', Mock(return_value=True)) + @patch( + 'openedx.core.djangoapps.video_config.services.VideoConfigService.is_hls_playback_enabled', + Mock(return_value=True) + ) @patch('xmodule.video_block.video_block.edxval_api.get_urls_for_profiles') def test_get_html_hls(self, get_urls_for_profiles): """ @@ -1309,7 +1314,10 @@ def test_poster_image_without_edx_video_id(self, get_course_video_image_url): assert "'poster': 'null'" in context - @patch('xmodule.video_block.video_block.HLSPlaybackEnabledFlag.feature_enabled', Mock(return_value=False)) + @patch( + 'openedx.core.djangoapps.video_config.services.VideoConfigService.is_hls_playback_enabled', + Mock(return_value=False) + ) def test_hls_primary_playback_on_toggling_hls_feature(self): """ Verify that `prioritize_hls` is set to `False` if `HLSPlaybackEnabledFlag` is disabled. @@ -1356,7 +1364,10 @@ def test_hls_primary_playback_on_toggling_hls_feature(self): 'result': 'false' }, ) - @patch('xmodule.video_block.video_block.HLSPlaybackEnabledFlag.feature_enabled', Mock(return_value=True)) + @patch( + 'openedx.core.djangoapps.video_config.services.VideoConfigService.is_hls_playback_enabled', + Mock(return_value=True) + ) def test_deprecate_youtube_course_waffle_flag(self, data): """ Tests various combinations of a `prioritize_hls` flag being set in waffle and overridden for a course. @@ -1417,7 +1428,10 @@ def setUp(self): ), ) @ddt.unpack - @patch('xmodule.video_block.video_block.HLSPlaybackEnabledFlag.feature_enabled', Mock(return_value=True)) + @patch( + 'openedx.core.djangoapps.video_config.services.VideoConfigService.is_hls_playback_enabled', + Mock(return_value=True) + ) def test_val_encoding_in_context(self, val_video_encodings, video_url): """ Tests that the val encodings correctly override the video url when the edx video id is set and @@ -1458,7 +1472,10 @@ def test_val_encoding_in_context(self, val_video_encodings, video_url): ), ) @ddt.unpack - @patch('xmodule.video_block.video_block.HLSPlaybackEnabledFlag.feature_enabled', Mock(return_value=True)) + @patch( + 'openedx.core.djangoapps.video_config.services.VideoConfigService.is_hls_playback_enabled', + Mock(return_value=True) + ) def test_val_encoding_in_context_without_external_youtube_source(self, val_video_encodings, video_url): """ Tests that the val encodings correctly override the video url when the edx video id is set and diff --git a/openedx/core/djangoapps/video_config/services.py b/openedx/core/djangoapps/video_config/services.py index 4ab5e5c4bd22..110c4ed05e53 100644 --- a/openedx/core/djangoapps/video_config/services.py +++ b/openedx/core/djangoapps/video_config/services.py @@ -12,7 +12,12 @@ from openedx.core.djangoapps.video_config import sharing from organizations.api import get_course_organization - +from openedx.core.djangoapps.video_config.models import ( + CourseYoutubeBlockedFlag, + HLSPlaybackEnabledFlag, +) +from openedx.core.djangoapps.video_config.toggles import TRANSCRIPT_FEEDBACK +from openedx.core.djangoapps.video_pipeline.config.waffle import DEPRECATE_YOUTUBE log = logging.getLogger(__name__) @@ -62,3 +67,27 @@ def get_public_sharing_context(self, video_block, course_key: CourseKey) -> dict context['sharing_sites_info'] = sharing_sites_info return context + + def is_transcript_feedback_enabled(self, course_id: CourseKey) -> bool: + """ + Check if transcript feedback is enabled for the course. + """ + return TRANSCRIPT_FEEDBACK.is_enabled(course_id) + + def is_youtube_deprecated(self, course_id: CourseKey) -> bool: + """ + Check if YouTube is deprecated for the course. + """ + return DEPRECATE_YOUTUBE.is_enabled(course_id) + + def is_youtube_blocked_for_course(self, course_id: CourseKey) -> bool: + """ + Check if YouTube is blocked for the course. + """ + return CourseYoutubeBlockedFlag.feature_enabled(course_id) + + def is_hls_playback_enabled(self, course_id: CourseKey) -> bool: + """ + Check if HLS playback is enabled for the course. + """ + return HLSPlaybackEnabledFlag.feature_enabled(course_id) diff --git a/xmodule/tests/test_video.py b/xmodule/tests/test_video.py index 1c32603fe7c1..be605aa12961 100644 --- a/xmodule/tests/test_video.py +++ b/xmodule/tests/test_video.py @@ -944,7 +944,10 @@ def test_student_view_data(self, field_data, expected_student_view_data): student_view_data = block.student_view_data() assert student_view_data == expected_student_view_data - @patch('xmodule.video_block.video_block.HLSPlaybackEnabledFlag.feature_enabled', Mock(return_value=True)) + @patch( + 'openedx.core.djangoapps.video_config.services.VideoConfigService.is_hls_playback_enabled', + Mock(return_value=True) + ) @patch('openedx.core.djangoapps.video_config.transcripts_utils.get_available_transcript_languages', Mock(return_value=['es'])) @patch('edxval.api.get_video_info_for_course_and_profiles', Mock(return_value={})) diff --git a/xmodule/video_block/video_block.py b/xmodule/video_block/video_block.py index 91448e2a47c1..fe1516be4603 100644 --- a/xmodule/video_block/video_block.py +++ b/xmodule/video_block/video_block.py @@ -22,6 +22,7 @@ from django.conf import settings from edx_django_utils.cache import RequestCache from lxml import etree +from opaque_keys.edx.keys import CourseKey from opaque_keys.edx.locator import AssetLocator from web_fragments.fragment import Fragment from xblock.completable import XBlockCompletionMode @@ -31,9 +32,6 @@ from xblocks_contrib.video import VideoBlock as _ExtractedVideoBlock from common.djangoapps.xblock_django.constants import ATTR_KEY_REQUEST_COUNTRY_CODE, ATTR_KEY_USER_ID -from openedx.core.djangoapps.video_config.models import HLSPlaybackEnabledFlag, CourseYoutubeBlockedFlag -from openedx.core.djangoapps.video_config.toggles import TRANSCRIPT_FEEDBACK -from openedx.core.djangoapps.video_pipeline.config.waffle import DEPRECATE_YOUTUBE from openedx.core.lib.cache_utils import request_cached from openedx.core.lib.license import LicenseMixin from xmodule.contentstore.content import StaticContent @@ -106,8 +104,8 @@ EXPORT_IMPORT_STATIC_DIR = 'static' -@XBlock.wants('settings', 'completion', 'i18n', 'request_cache') -@XBlock.needs('mako', 'user', 'video_config') +@XBlock.wants('settings', 'completion', 'i18n', 'request_cache', 'video_config') +@XBlock.needs('mako', 'user') class _BuiltInVideoBlock( VideoFields, VideoTranscriptsMixin, VideoStudioViewHandlers, VideoStudentViewHandlers, EmptyDataRawMixin, XmlMixin, EditingMixin, XModuleToXBlockMixin, @@ -188,18 +186,26 @@ def get_transcripts_for_student(self, transcripts, dest_lang=None): sorted_languages = OrderedDict(sorted_languages) return track_url, transcript_language, sorted_languages + def is_hls_playback_enabled(self, course_id: CourseKey) -> bool: + """ + Check if HLS playback is enabled for the course. + """ + video_config_service = self.runtime.service(self, 'video_config') + return video_config_service.is_hls_playback_enabled(course_id) if video_config_service else False + @property def youtube_deprecated(self): """ Return True if youtube is deprecated and hls as primary playback is enabled else False """ + video_config_service = self.runtime.service(self, 'video_config') # Return False if `hls` playback feature is disabled. - if not HLSPlaybackEnabledFlag.feature_enabled(self.location.course_key): + if not self.is_hls_playback_enabled(self.location.course_key): return False # check if youtube has been deprecated and hls as primary playback # is enabled for this course - return DEPRECATE_YOUTUBE.is_enabled(self.location.course_key) + return video_config_service.is_youtube_deprecated(self.location.course_key) if video_config_service else False def youtube_disabled_for_course(self): # lint-amnesty, pylint: disable=missing-function-docstring if not self.location.context_key.is_course: @@ -209,7 +215,9 @@ def youtube_disabled_for_course(self): # lint-amnesty, pylint: disable=missing- if cache_response.is_found: return cache_response.value - youtube_is_disabled = CourseYoutubeBlockedFlag.feature_enabled(self.location.course_key) + video_config_service = self.runtime.service(self, 'video_config') + youtube_is_disabled = video_config_service.is_youtube_blocked_for_course( + self.location.course_key) if video_config_service else False request_cache.set(self.location.context_key, youtube_is_disabled) return youtube_is_disabled @@ -300,7 +308,7 @@ def get_html(self, view=STUDENT_VIEW, context=None): # lint-amnesty, pylint: di try: val_profiles = ["youtube", "desktop_webm", "desktop_mp4"] - if HLSPlaybackEnabledFlag.feature_enabled(self.course_id): + if self.is_hls_playback_enabled(self.course_id): val_profiles.append('hls') # strip edx_video_id to prevent ValVideoNotFoundError error if unwanted spaces are there. TNL-5769 @@ -499,7 +507,9 @@ def is_transcript_feedback_enabled(self): return False # Only courses support this feature at all (not libraries) try: # Video transcript feedback must be enabled in order to show the widget - feature_enabled = TRANSCRIPT_FEEDBACK.is_enabled(self.context_key) + video_config_service = self.runtime.service(self, 'video_config') + feature_enabled = video_config_service.is_transcript_feedback_enabled( + self.context_key) if video_config_service else False except Exception as err: # pylint: disable=broad-except log.exception(f"Error retrieving course for course ID: {self.context_key}") return False @@ -881,7 +891,7 @@ def get_youtube_link(video_id): if self.edx_video_id and edxval_api: val_profiles = ['youtube', 'desktop_webm', 'desktop_mp4'] - if HLSPlaybackEnabledFlag.feature_enabled(self.scope_ids.usage_id.context_key.for_branch(None)): + if self.is_hls_playback_enabled(self.scope_ids.usage_id.context_key.for_branch(None)): val_profiles.append('hls') # Get video encodings for val profiles. @@ -1137,7 +1147,7 @@ def student_view_data(self, context=None): # Check in VAL data first if edx_video_id exists if self.edx_video_id: video_profile_names = context.get("profiles", ["mobile_low", 'desktop_mp4', 'desktop_webm', 'mobile_high']) - if HLSPlaybackEnabledFlag.feature_enabled(self.location.course_key) and 'hls' not in video_profile_names: + if self.is_hls_playback_enabled(self.location.course_key) and 'hls' not in video_profile_names: video_profile_names.append('hls') # get and cache bulk VAL data for course