diff --git a/lms/djangoapps/courseware/tests/test_video_mongo.py b/lms/djangoapps/courseware/tests/test_video_mongo.py index aced9d01c6..dd728597c9 100644 --- a/lms/djangoapps/courseware/tests/test_video_mongo.py +++ b/lms/djangoapps/courseware/tests/test_video_mongo.py @@ -53,7 +53,7 @@ from openedx.core.djangoapps.waffle_utils.models import WaffleFlagCourseOverride from openedx.core.djangolib.testing.utils import CacheIsolationTestCase from .test_video_handlers import BaseTestVideoXBlock, TestVideo -from .test_video_xml import SOURCE_XML +from .test_video_xml import SOURCE_XML, PUBLIC_SOURCE_XML MODULESTORES = { ModuleStoreEnum.Type.mongo: TEST_DATA_MONGO_MODULESTORE, @@ -132,6 +132,7 @@ class TestVideoYouTube(TestVideo): # lint-amnesty, pylint: disable=missing-clas {'display_name': 'Text (.txt) file', 'value': 'txt'} ], 'poster': 'null', + 'public_video_url': None, } mako_service = self.item_descriptor.xmodule_runtime.service(self.item_descriptor, 'mako') @@ -215,6 +216,7 @@ class TestVideoNonYouTube(TestVideo): # pylint: disable=test-inherits-tests {'display_name': 'Text (.txt) file', 'value': 'txt'} ], 'poster': 'null', + 'public_video_url': None, } mako_service = self.item_descriptor.xmodule_runtime.service(self.item_descriptor, 'mako') @@ -226,6 +228,25 @@ class TestVideoNonYouTube(TestVideo): # pylint: disable=test-inherits-tests assert expected_result['display_name'] == 'A Name' +@ddt.ddt +class TestVideoPublicAccess(BaseTestVideoXBlock): + """Test video public access.""" + DATA = PUBLIC_SOURCE_XML + MODEL_DATA = { + 'data': DATA, + } + METADATA = {} + + @ddt.data(True, False) + def test_public_video_url(self, is_lms_platform): + """Test public video url.""" + assert self.item_descriptor.public_access is True + with patch.object(self.item_descriptor, '_is_lms_platform', return_value=is_lms_platform): + context = self.item_descriptor.render(STUDENT_VIEW).content + # public video url iif is_lms_platform and public_access are true + assert bool(get_context_dict_from_string(context)['public_video_url']) is is_lms_platform + + @ddt.ddt class TestGetHtmlMethod(BaseTestVideoXBlock): ''' @@ -356,6 +377,7 @@ class TestGetHtmlMethod(BaseTestVideoXBlock): {'display_name': 'Text (.txt) file', 'value': 'txt'} ], 'poster': 'null', + 'public_video_url': None, } for data in cases: @@ -476,6 +498,7 @@ class TestGetHtmlMethod(BaseTestVideoXBlock): {'display_name': 'Text (.txt) file', 'value': 'txt'} ], 'poster': 'null', + 'public_video_url': None, } initial_context['metadata']['duration'] = None @@ -602,6 +625,7 @@ class TestGetHtmlMethod(BaseTestVideoXBlock): {'display_name': 'Text (.txt) file', 'value': 'txt'} ], 'poster': 'null', + 'public_video_url': None, 'metadata': metadata } @@ -775,6 +799,7 @@ class TestGetHtmlMethod(BaseTestVideoXBlock): {'display_name': 'Text (.txt) file', 'value': 'txt'} ], 'poster': 'null', + 'public_video_url': None, 'metadata': metadata, } @@ -888,6 +913,7 @@ class TestGetHtmlMethod(BaseTestVideoXBlock): {'display_name': 'SubRip (.srt) file', 'value': 'srt'}, {'display_name': 'Text (.txt) file', 'value': 'txt'} ], + 'public_video_url': None, 'poster': 'null', } initial_context['metadata']['duration'] = None @@ -984,6 +1010,7 @@ class TestGetHtmlMethod(BaseTestVideoXBlock): {'display_name': 'SubRip (.srt) file', 'value': 'srt'}, {'display_name': 'Text (.txt) file', 'value': 'txt'} ], + 'public_video_url': None, 'poster': 'null', } initial_context['metadata']['duration'] = None @@ -2254,6 +2281,7 @@ class TestVideoWithBumper(TestVideo): # pylint: disable=test-inherits-tests {'display_name': 'SubRip (.srt) file', 'value': 'srt'}, {'display_name': 'Text (.txt) file', 'value': 'txt'} ], + 'public_video_url': None, 'poster': json.dumps(OrderedDict({ 'url': 'http://img.youtube.com/vi/ZwkTiUPN0mg/0.jpg', 'type': 'youtube' @@ -2335,6 +2363,7 @@ class TestAutoAdvanceVideo(TestVideo): # lint-amnesty, pylint: disable=test-inh {'display_name': 'SubRip (.srt) file', 'value': 'srt'}, {'display_name': 'Text (.txt) file', 'value': 'txt'} ], + 'public_video_url': None, 'poster': 'null' } return context diff --git a/lms/djangoapps/courseware/tests/test_video_xml.py b/lms/djangoapps/courseware/tests/test_video_xml.py index 67787f9121..2b454bef63 100644 --- a/lms/djangoapps/courseware/tests/test_video_xml.py +++ b/lms/djangoapps/courseware/tests/test_video_xml.py @@ -32,6 +32,21 @@ SOURCE_XML = """ """ +PUBLIC_SOURCE_XML = """ + +""" + class VideoBlockLogicTest(TestCase): """Tests for logic of VideoBlock.""" diff --git a/lms/templates/video.html b/lms/templates/video.html index 39e93b55e8..36f91b47c0 100644 --- a/lms/templates/video.html +++ b/lms/templates/video.html @@ -55,6 +55,17 @@ from openedx.core.djangolib.js_utils import ( ${_('Download video file')} + % if public_video_url: +
+ + ${_('Share on Twitter')} + + % endif % endif % if track: @@ -117,3 +128,19 @@ from openedx.core.djangolib.js_utils import ( } % endif; +% if public_video_url: + +% endif diff --git a/xmodule/video_block/video_block.py b/xmodule/video_block/video_block.py index f5ec971212..0609fe30ef 100644 --- a/xmodule/video_block/video_block.py +++ b/xmodule/video_block/video_block.py @@ -18,8 +18,10 @@ import json import logging from collections import OrderedDict, defaultdict from operator import itemgetter +from urllib.parse import urljoin from django.conf import settings +from django.urls import reverse from edx_django_utils.cache import RequestCache from lxml import etree from opaque_keys.edx.locator import AssetLocator @@ -28,6 +30,7 @@ from xblock.completable import XBlockCompletionMode from xblock.core import XBlock from xblock.fields import ScopeIds from xblock.runtime import KvsFieldData +from lms.djangoapps.lms_xblock.runtime import LmsModuleSystem from common.djangoapps.xblock_django.constants import ATTR_KEY_REQUEST_COUNTRY_CODE from openedx.core.djangoapps.video_config.models import HLSPlaybackEnabledFlag, CourseYoutubeBlockedFlag @@ -474,9 +477,28 @@ class VideoBlock( 'track': track_url, 'transcript_download_format': transcript_download_format, 'transcript_download_formats_list': self.fields['transcript_download_format'].values, # lint-amnesty, pylint: disable=unsubscriptable-object + # provide the video url iif the video is public and we are in LMS. + # Reverse render_public_video_xblock is not available in studio. + 'public_video_url': self._get_public_video_url(), } + return self.runtime.service(self, 'mako').render_template('video.html', template_context) + def _is_lms_platform(self): + """ + Returns True if the platform is LMS. + """ + return isinstance(self.xmodule_runtime, LmsModuleSystem) + + def _get_public_video_url(self): + """ + Returns the public video url + """ + return urljoin( + settings.LMS_ROOT_URL, + reverse('render_public_video_xblock', kwargs={'usage_key_string': str(self.location)}) + ) if self.public_access and self._is_lms_platform() else None + def validate(self): """ Validates the state of this Video XBlock instance. This