Commit 4878f6e8 by Don Mitchell

Implement edit info as mixin for split

LMS-11183, LMS-11184
parent 7b52d45a
......@@ -11,11 +11,12 @@ from ..exceptions import ItemNotFoundError
from .split_mongo_kvs import SplitMongoKVS
from fs.osfs import OSFS
from .definition_lazy_loader import DefinitionLazyLoader
from xmodule.modulestore.edit_info import EditInfoRuntimeMixin
log = logging.getLogger(__name__)
class CachingDescriptorSystem(MakoDescriptorSystem):
class CachingDescriptorSystem(MakoDescriptorSystem, EditInfoRuntimeMixin):
"""
A system that has a cache of a course version's json that it will use to load modules
from, with a backup of calling to the underlying modulestore for more data.
......@@ -89,6 +90,19 @@ class CachingDescriptorSystem(MakoDescriptorSystem):
run=course_info.get('run'),
branch=course_info.get('branch'),
)
json_data = self.get_module_data(block_id, course_key)
class_ = self.load_block_type(json_data.get('category'))
new_item = self.xblock_from_json(class_, course_key, block_id, json_data, course_entry_override, **kwargs)
return new_item
def get_module_data(self, block_id, course_key):
"""
Get block from module_data adding it to module_data if it's not already there but is in the structure
Raises:
ItemNotFoundError if block is not in the structure
"""
json_data = self.module_data.get(block_id)
if json_data is None:
# deeper than initial descendant fetch or doesn't exist
......@@ -97,9 +111,7 @@ class CachingDescriptorSystem(MakoDescriptorSystem):
if json_data is None:
raise ItemNotFoundError(block_id)
class_ = self.load_block_type(json_data.get('category'))
new_item = self.xblock_from_json(class_, course_key, block_id, json_data, course_entry_override, **kwargs)
return new_item
return json_data
# xblock's runtime does not always pass enough contextual information to figure out
# which named container (course x branch) or which parent is requesting an item. Because split allows
......@@ -181,12 +193,8 @@ class CachingDescriptorSystem(MakoDescriptorSystem):
)
edit_info = json_data.get('edit_info', {})
module.edited_by = edit_info.get('edited_by')
module.edited_on = edit_info.get('edited_on')
module.subtree_edited_by = None # TODO - addressed with LMS-11183
module.subtree_edited_on = None # TODO - addressed with LMS-11183
module.published_by = None # TODO - addressed with LMS-11184
module.published_date = None # TODO - addressed with LMS-11184
module._edited_by = edit_info.get('edited_by')
module._edited_on = edit_info.get('edited_on')
module.previous_version = edit_info.get('previous_version')
module.update_version = edit_info.get('update_version')
module.source_version = edit_info.get('source_version', None)
......@@ -199,3 +207,79 @@ class CachingDescriptorSystem(MakoDescriptorSystem):
self.local_modules[block_locator] = module
return module
def get_edited_by(self, xblock):
"""
See :meth: cms.lib.xblock.runtime.EditInfoRuntimeMixin.get_edited_by
"""
return xblock._edited_by
def get_edited_on(self, xblock):
"""
See :class: cms.lib.xblock.runtime.EditInfoRuntimeMixin
"""
return xblock._edited_on
def get_subtree_edited_by(self, xblock):
"""
See :class: cms.lib.xblock.runtime.EditInfoRuntimeMixin
"""
if not hasattr(xblock, '_subtree_edited_by'):
json_data = self.module_data[xblock.location.block_id]
if '_subtree_edited_by' not in json_data.setdefault('edit_info', {}):
self._compute_subtree_edited_internal(
xblock.location.block_id, json_data, xblock.location.course_key
)
setattr(xblock, '_subtree_edited_by', json_data['edit_info']['_subtree_edited_by'])
return getattr(xblock, '_subtree_edited_by')
def get_subtree_edited_on(self, xblock):
"""
See :class: cms.lib.xblock.runtime.EditInfoRuntimeMixin
"""
if not hasattr(xblock, '_subtree_edited_on'):
json_data = self.module_data[xblock.location.block_id]
if '_subtree_edited_on' not in json_data.setdefault('edit_info', {}):
self._compute_subtree_edited_internal(
xblock.location.block_id, json_data, xblock.location.course_key
)
setattr(xblock, '_subtree_edited_on', json_data['edit_info']['_subtree_edited_on'])
return getattr(xblock, '_subtree_edited_on')
def get_published_by(self, xblock):
"""
See :class: cms.lib.xblock.runtime.EditInfoRuntimeMixin
"""
if not hasattr(xblock, '_published_by'):
self.modulestore.compute_published_info_internal(xblock)
return getattr(xblock, '_published_by', None)
def get_published_on(self, xblock):
"""
See :class: cms.lib.xblock.runtime.EditInfoRuntimeMixin
"""
if not hasattr(xblock, '_published_on'):
self.modulestore.compute_published_info_internal(xblock)
return getattr(xblock, '_published_on', None)
def _compute_subtree_edited_internal(self, block_id, json_data, course_key):
"""
Recurse the subtree finding the max edited_on date and its concomitant edited_by. Cache it
"""
max_date = json_data['edit_info']['edited_on']
max_by = json_data['edit_info']['edited_by']
for child in json_data.get('fields', {}).get('children', []):
child_data = self.get_module_data(child, course_key)
if '_subtree_edited_on' not in json_data.setdefault('edit_info', {}):
self._compute_subtree_edited_internal(child, child_data)
if child_data['edit_info']['_subtree_edited_on'] > max_date:
max_date = child_data['edit_info']['_subtree_edited_on']
max_by = child_data['edit_info']['_subtree_edited_by']
json_data['edit_info']['_subtree_edited_on'] = max_date
json_data['edit_info']['_subtree_edited_by'] = max_by
......@@ -387,3 +387,11 @@ class DraftVersioningModuleStore(ModuleStoreDraftAndPublished, SplitMongoModuleS
return self._update_item_from_fields(
user_id, course_key, block_type, block_id, partitioned_fields, None, allow_not_found=True, force=True
)
def compute_published_info_internal(self, xblock):
"""
Get the published branch and find when it was published if it was. Cache the results in the xblock
"""
published_block = self._get_head(xblock, ModuleStoreEnum.BranchName.published)
setattr(xblock, '_published_by', published_block['edit_info']['edited_by'])
setattr(xblock, '_published_on', published_block['edit_info']['edited_on'])
......@@ -13,6 +13,8 @@ from uuid import uuid4
# before importing the module
# TODO remove this import and the configuration -- xmodule should not depend on django!
from django.conf import settings
from xmodule.modulestore.edit_info import EditInfoMixin
if not settings.configured:
settings.configure()
......@@ -52,6 +54,7 @@ class TestMixedModuleStore(unittest.TestCase):
'default_class': DEFAULT_CLASS,
'fs_root': DATA_DIR,
'render_template': RENDER_TEMPLATE,
'xblock_mixins': (EditInfoMixin,)
}
DOC_STORE_CONFIG = {
'host': HOST,
......
......@@ -23,6 +23,7 @@ from xmodule.fields import Date, Timedelta
from xmodule.modulestore.split_mongo.split import SplitMongoModuleStore
from xmodule.modulestore.tests.test_modulestore import check_has_course_method
from xmodule.modulestore.tests.mongo_connection import MONGO_PORT_NUM, MONGO_HOST
from xmodule.modulestore.edit_info import EditInfoMixin
BRANCH_NAME_DRAFT = ModuleStoreEnum.BranchName.draft
......@@ -45,7 +46,7 @@ class SplitModuleTest(unittest.TestCase):
modulestore_options = {
'default_class': 'xmodule.raw_module.RawDescriptor',
'fs_root': '',
'xblock_mixins': (InheritanceMixin, XModuleMixin)
'xblock_mixins': (InheritanceMixin, XModuleMixin, EditInfoMixin)
}
MODULESTORE = {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment