Files
edx-platform/lms/djangoapps/lms_xblock/runtime.py
2023-04-26 17:10:54 +02:00

174 lines
5.4 KiB
Python

"""
Module implementing `xblock.runtime.Runtime` functionality for the LMS
"""
from django.conf import settings
from django.urls import reverse
from lms.djangoapps.lms_xblock.models import XBlockAsidesConfig
from openedx.core.djangoapps.user_api.course_tag import api as user_course_tag_api
from openedx.core.lib.url_utils import quote_slashes
from openedx.core.lib.xblock_utils import wrap_xblock_aside, xblock_local_resource_url
def handler_url(block, handler_name, suffix='', query='', thirdparty=False):
"""
This method matches the signature for `xblock.runtime:Runtime.handler_url()`
:param block: The block to generate the url for
:param handler_name: The handler on that block that the url should resolve to
:param suffix: Any path suffix that should be added to the handler url
:param query: Any query string that should be added to the handler url
(which should not include an initial ? or &)
:param thirdparty: If true, return a fully-qualified URL instead of relative
URL. This is useful for URLs to be used by third-party services.
"""
view_name = 'xblock_handler'
if handler_name:
# Be sure this is really a handler.
#
# We're checking the .__class__ instead of the block itself to avoid
# auto-proxying from Descriptor -> XBlock, in case descriptors want
# to ask for handler URLs without a student context.
func = getattr(block.__class__, handler_name, None)
if not func:
raise ValueError(f"{handler_name!r} is not a function name")
if thirdparty:
view_name = 'xblock_handler_noauth'
url = reverse(view_name, kwargs={
'course_id': str(block.scope_ids.usage_id.context_key),
'usage_id': quote_slashes(str(block.scope_ids.usage_id)),
'handler': handler_name,
'suffix': suffix,
})
# If suffix is an empty string, remove the trailing '/'
if not suffix:
url = url.rstrip('/')
# If there is a query string, append it
if query:
url += '?' + query
# If third-party, return fully-qualified url
if thirdparty:
scheme = "https" if settings.HTTPS == "on" else "http"
url = '{scheme}://{host}{path}'.format(
scheme=scheme,
host=settings.SITE_NAME,
path=url
)
return url
def local_resource_url(block, uri):
"""
local_resource_url for Studio
"""
return xblock_local_resource_url(block, uri)
def lms_wrappers_aside(block, aside, view, frag, context, request_token=None):
"""
Creates a div which identifies the aside, points to the original block,
and writes out the json_init_args into a script tag.
The default implementation creates a frag to wraps frag w/ a div identifying the xblock. If you have
javascript, you'll need to override this impl
"""
if not frag.content:
return frag
runtime_class = 'LmsRuntime'
extra_data = {
'block-id': quote_slashes(str(block.scope_ids.usage_id)),
'course-id': quote_slashes(str(block.scope_ids.usage_id.context_key)),
'url-selector': 'asideBaseUrl',
'runtime-class': runtime_class,
}
if request_token:
extra_data['request-token'] = request_token
return wrap_xblock_aside(
runtime_class,
aside,
view,
frag,
context,
usage_id_serializer=str,
request_token=request_token,
extra_data=extra_data,
)
def lms_applicable_aside_types(block, applicable_aside_types=None):
"""
Return all of the asides which might be decorating this `block`.
Arguments:
block (:class:`.XBlock`): The block to render retrieve asides for.
"""
config = XBlockAsidesConfig.current()
if not config.enabled:
return []
if block.scope_ids.block_type in config.disabled_blocks.split():
return []
# TODO: aside_type != 'acid_aside' check should be removed once AcidBlock is only installed during tests
# (see https://openedx.atlassian.net/browse/TE-811)
return [
aside_type
for aside_type in applicable_aside_types(block)
if aside_type != 'acid_aside'
]
class UserTagsService:
"""
A runtime class that provides an interface to the user service. It handles filling in
the current course id and current user.
"""
COURSE_SCOPE = user_course_tag_api.COURSE_SCOPE
def __init__(self, user, course_id):
self._user = user
self._course_id = course_id
def get_tag(self, scope, key):
"""
Get a user tag for the current course and the current user for a given key
scope: the current scope of the runtime
key: the key for the value we want
"""
if scope != user_course_tag_api.COURSE_SCOPE:
raise ValueError(f"unexpected scope {scope}")
return user_course_tag_api.get_course_tag(
self._user,
self._course_id, key
)
def set_tag(self, scope, key, value):
"""
Set the user tag for the current course and the current user for a given key
scope: the current scope of the runtime
key: the key that to the value to be set
value: the value to set
"""
if scope != user_course_tag_api.COURSE_SCOPE:
raise ValueError(f"unexpected scope {scope}")
return user_course_tag_api.set_course_tag(
self._user,
self._course_id, key, value
)