diff --git a/openedx/features/offline_mode/assets_management.py b/openedx/features/offline_mode/assets_management.py index 4d4daf12394c..e90d00fe20d6 100644 --- a/openedx/features/offline_mode/assets_management.py +++ b/openedx/features/offline_mode/assets_management.py @@ -79,9 +79,9 @@ def create_subdirectories_for_asset(file_path): os.mkdir(out_dir_name) -def remove_old_files(xblock): +def clean_outdated_xblock_files(xblock): """ - Removes the old 'offline_content.zip' files from media storage. + Removes the old zip file with Offline Content from media storage. Args: (XBlock): The XBlock instance """ diff --git a/openedx/features/offline_mode/constants.py b/openedx/features/offline_mode/constants.py index 771b341505aa..a1337a7029c1 100644 --- a/openedx/features/offline_mode/constants.py +++ b/openedx/features/offline_mode/constants.py @@ -9,7 +9,7 @@ MATHJAX_CDN_URL = f'https://cdn.jsdelivr.net/npm/mathjax@{MATHJAX_VERSION}/MathJax.js' MATHJAX_STATIC_PATH = os.path.join('assets', 'js', f'MathJax-{MATHJAX_VERSION}.js') -DEFAULT_OFFLINE_SUPPORTED_XBLOCKS = ['html', 'problem'] +DEFAULT_OFFLINE_SUPPORTED_XBLOCKS = ['html'] OFFLINE_SUPPORTED_XBLOCKS = getattr(settings, 'OFFLINE_SUPPORTED_XBLOCKS', DEFAULT_OFFLINE_SUPPORTED_XBLOCKS) RETRY_BACKOFF_INITIAL_TIMEOUT = 60 # one minute diff --git a/openedx/features/offline_mode/utils.py b/openedx/features/offline_mode/storage_management.py similarity index 76% rename from openedx/features/offline_mode/utils.py rename to openedx/features/offline_mode/storage_management.py index 860a1fe1b1fa..20aa7fb25d85 100644 --- a/openedx/features/offline_mode/utils.py +++ b/openedx/features/offline_mode/storage_management.py @@ -13,42 +13,49 @@ from openedx.core.storage import get_storage from zipfile import ZipFile -from .assets_management import block_storage_path, remove_old_files, is_modified +from .assets_management import block_storage_path, clean_outdated_xblock_files, is_modified from .html_manipulator import HtmlManipulator User = get_user_model() log = logging.getLogger(__name__) -class SaveOfflineContentToStorage: +class OfflineContentStorageManager: """ Creates zip file with Offline Content in the media storage. """ - def __init__(self, storage_class=None, storage_kwargs=None): + def __init__(self, xblock, html_data, storage_class=None, storage_kwargs=None): + """ + Creates `SaveOfflineContentToStorage` object. + + Args: + xblock (XBlock): The XBlock instance + html_data (str): The rendered HTML representation of the XBlock + storage_class: Used media storage class. + storage_kwargs (dict): Additional storage attributes. + """ if storage_kwargs is None: storage_kwargs = {} + self.xblock = xblock + self.html_data = html_data self.storage = get_storage(storage_class, **storage_kwargs) - def generate_offline_content(self, xblock, html_data): + def generate_offline_content(self): """ Generates archive with XBlock content for offline mode. - - Args: - xblock (XBlock): The XBlock instance - html_data (str): The rendered HTML representation of the XBlock """ - if not is_modified(xblock): + if not is_modified(self.xblock): return - base_path = block_storage_path(xblock) - remove_old_files(xblock) + base_path = block_storage_path(self.xblock) + clean_outdated_xblock_files(self.xblock) tmp_dir = mkdtemp() try: - self.save_xblock_html(tmp_dir, xblock, html_data) - self.create_zip_file(tmp_dir, base_path, f'{xblock.location.block_id}.zip') + self.save_xblock_html(tmp_dir) + self.create_zip_file(tmp_dir, base_path, f'{self.xblock.location.block_id}.zip') except Http404: log.error( f'Block {xblock.location.block_id} cannot be fetched from course' @@ -57,8 +64,7 @@ def generate_offline_content(self, xblock, html_data): finally: shutil.rmtree(tmp_dir, ignore_errors=True) - @staticmethod - def save_xblock_html(tmp_dir, xblock, html_data): + def save_xblock_html(self, tmp_dir): """ Saves the XBlock HTML content to a file. @@ -66,10 +72,8 @@ def save_xblock_html(tmp_dir, xblock, html_data): Args: tmp_dir (str): The temporary directory path to save the xblock content - xblock (XBlock): The XBlock instance - html_data (str): The rendered HTML representation of the XBlock """ - html_manipulator = HtmlManipulator(xblock, html_data, tmp_dir) + html_manipulator = HtmlManipulator(self.xblock, self.html_data, tmp_dir) updated_html = html_manipulator.process_html() with open(os.path.join(tmp_dir, 'index.html'), 'w') as file: @@ -84,14 +88,16 @@ def create_zip_file(self, temp_dir, base_path, file_name): base_path (str): The base path directory to save the zip file file_name (str): The name of the zip file """ - with ZipFile(temp_dir + '/' + file_name, 'w') as zip_file: + file_path = os.path.join(temp_dir, file_name) + + with ZipFile(file_path, 'w') as zip_file: zip_file.write(os.path.join(temp_dir, 'index.html'), 'index.html') self.add_files_to_zip_recursively( zip_file, current_base_path=os.path.join(temp_dir, 'assets'), current_path_in_zip='assets', ) - with open(temp_dir + '/' + file_name, 'rb') as buffered_zip: + with open(file_path, 'rb') as buffered_zip: content_file = ContentFile(buffered_zip.read()) self.storage.save(base_path + file_name, content_file) diff --git a/openedx/features/offline_mode/tasks.py b/openedx/features/offline_mode/tasks.py index 00c4de1bb6ed..beea85e1421e 100644 --- a/openedx/features/offline_mode/tasks.py +++ b/openedx/features/offline_mode/tasks.py @@ -10,7 +10,7 @@ from .constants import MAX_RETRY_ATTEMPTS, OFFLINE_SUPPORTED_XBLOCKS, RETRY_BACKOFF_INITIAL_TIMEOUT from .renderer import XBlockRenderer -from .utils import SaveOfflineContentToStorage +from .storage_management import OfflineContentStorageManager @shared_task @@ -42,4 +42,4 @@ def generate_offline_content_for_block(block_id, html_data): """ block_usage_key = UsageKey.from_string(block_id) xblock = modulestore().get_item(block_usage_key) - SaveOfflineContentToStorage().generate_offline_content(xblock, html_data) + OfflineContentStorageManager(xblock, html_data).generate_offline_content()