Commit 0866f056 by Feanil Patel

Merge pull request #7910 from edx/jeskew/PLAT_452_drafts_show_as_published

Fix issue PLAT-452: Draft block showing as published.
parents 270ac747 8ca57f83
...@@ -352,16 +352,21 @@ class EditInfo(object): ...@@ -352,16 +352,21 @@ class EditInfo(object):
self.original_usage = edit_info.get('original_usage', None) self.original_usage = edit_info.get('original_usage', None)
self.original_usage_version = edit_info.get('original_usage_version', None) self.original_usage_version = edit_info.get('original_usage_version', None)
def __str__(self): def __repr__(self):
return ("EditInfo(previous_version={0.previous_version}, " # pylint: disable=bad-continuation, redundant-keyword-arg
"update_version={0.update_version}, " return ("{classname}(previous_version={self.previous_version}, "
"source_version={0.source_version}, " "update_version={self.update_version}, "
"edited_on={0.edited_on}, " "source_version={source_version}, "
"edited_by={0.edited_by}, " "edited_on={self.edited_on}, "
"original_usage={0.original_usage}, " "edited_by={self.edited_by}, "
"original_usage_version={0.original_usage_version}, " "original_usage={self.original_usage}, "
"_subtree_edited_on={0._subtree_edited_on}, " "original_usage_version={self.original_usage_version}, "
"_subtree_edited_by={0._subtree_edited_by})").format(self) "_subtree_edited_on={self._subtree_edited_on}, "
"_subtree_edited_by={self._subtree_edited_by})").format(
self=self,
classname=self.__class__.__name__,
source_version="UNSET" if self.source_version is None else self.source_version,
) # pylint: disable=bad-continuation
class BlockData(object): class BlockData(object):
...@@ -408,13 +413,17 @@ class BlockData(object): ...@@ -408,13 +413,17 @@ class BlockData(object):
# EditInfo object containing all versioning/editing data. # EditInfo object containing all versioning/editing data.
self.edit_info = EditInfo(**block_data.get('edit_info', {})) self.edit_info = EditInfo(**block_data.get('edit_info', {}))
def __str__(self): def __repr__(self):
return ("BlockData(fields={0.fields}, " # pylint: disable=bad-continuation, redundant-keyword-arg
"block_type={0.block_type}, " return ("{classname}(fields={self.fields}, "
"definition={0.definition}, " "block_type={self.block_type}, "
"definition_loaded={0.definition_loaded}, " "definition={self.definition}, "
"defaults={0.defaults}, " "definition_loaded={self.definition_loaded}, "
"edit_info={0.edit_info})").format(self) "defaults={self.defaults}, "
"edit_info={self.edit_info})").format(
self=self,
classname=self.__class__.__name__,
) # pylint: disable=bad-continuation
new_contract('BlockData', BlockData) new_contract('BlockData', BlockData)
......
...@@ -2831,6 +2831,8 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase): ...@@ -2831,6 +2831,8 @@ class SplitMongoModuleStore(SplitBulkWriteMixin, ModuleStoreWriteBase):
# perhaps replace by fixing the views or Field Reference*.from_json to return a Key # perhaps replace by fixing the views or Field Reference*.from_json to return a Key
if isinstance(reference, basestring): if isinstance(reference, basestring):
reference = BlockUsageLocator.from_string(reference) reference = BlockUsageLocator.from_string(reference)
elif isinstance(reference, BlockKey):
return reference
return BlockKey.from_usage_key(reference) return BlockKey.from_usage_key(reference)
for field_name, value in fields.iteritems(): for field_name, value in fields.iteritems():
......
...@@ -494,11 +494,14 @@ class DraftVersioningModuleStore(SplitMongoModuleStore, ModuleStoreDraftAndPubli ...@@ -494,11 +494,14 @@ class DraftVersioningModuleStore(SplitMongoModuleStore, ModuleStoreDraftAndPubli
block_id = self.DEFAULT_ROOT_LIBRARY_BLOCK_ID block_id = self.DEFAULT_ROOT_LIBRARY_BLOCK_ID
new_usage_key = course_key.make_usage_key(block_type, block_id) new_usage_key = course_key.make_usage_key(block_type, block_id)
# Only the course import process calls import_xblock(). If the branch setting is published_only,
# then the non-draft blocks are being imported.
if self.get_branch_setting() == ModuleStoreEnum.Branch.published_only: if self.get_branch_setting() == ModuleStoreEnum.Branch.published_only:
# override existing draft (PLAT-297, PLAT-299). NOTE: this has the effect of removing # Override any existing drafts (PLAT-297, PLAT-299). This import/publish step removes
# any local changes w/ the import. # any local changes during the course import.
draft_course = course_key.for_branch(ModuleStoreEnum.BranchName.draft) draft_course = course_key.for_branch(ModuleStoreEnum.BranchName.draft)
with self.branch_setting(ModuleStoreEnum.Branch.draft_preferred, draft_course): with self.branch_setting(ModuleStoreEnum.Branch.draft_preferred, draft_course):
# Importing the block and publishing the block links the draft & published blocks' version history.
draft_block = self.import_xblock(user_id, draft_course, block_type, block_id, fields, runtime) draft_block = self.import_xblock(user_id, draft_course, block_type, block_id, fields, runtime)
return self.publish(draft_block.location.version_agnostic(), user_id, blacklist=EXCLUDE_ALL, **kwargs) return self.publish(draft_block.location.version_agnostic(), user_id, blacklist=EXCLUDE_ALL, **kwargs)
......
...@@ -9,7 +9,7 @@ from xmodule.x_module import XModuleMixin ...@@ -9,7 +9,7 @@ from xmodule.x_module import XModuleMixin
from opaque_keys.edx.locations import Location from opaque_keys.edx.locations import Location
from xmodule.modulestore import ModuleStoreEnum from xmodule.modulestore import ModuleStoreEnum
from xmodule.modulestore.inheritance import InheritanceMixin from xmodule.modulestore.inheritance import InheritanceMixin
from xmodule.modulestore.xml_importer import _import_module_and_update_references from xmodule.modulestore.xml_importer import _update_and_import_module
from xmodule.modulestore.tests.mongo_connection import MONGO_PORT_NUM, MONGO_HOST from xmodule.modulestore.tests.mongo_connection import MONGO_PORT_NUM, MONGO_HOST
from opaque_keys.edx.locations import SlashSeparatedCourseKey from opaque_keys.edx.locations import SlashSeparatedCourseKey
from xmodule.tests import DATA_DIR from xmodule.tests import DATA_DIR
...@@ -144,7 +144,7 @@ class RemapNamespaceTest(ModuleStoreNoSettings): ...@@ -144,7 +144,7 @@ class RemapNamespaceTest(ModuleStoreNoSettings):
# Move to different runtime w/ different course id # Move to different runtime w/ different course id
target_location_namespace = SlashSeparatedCourseKey("org", "course", "run") target_location_namespace = SlashSeparatedCourseKey("org", "course", "run")
new_version = _import_module_and_update_references( new_version = _update_and_import_module(
self.xblock, self.xblock,
modulestore(), modulestore(),
999, 999,
...@@ -181,7 +181,7 @@ class RemapNamespaceTest(ModuleStoreNoSettings): ...@@ -181,7 +181,7 @@ class RemapNamespaceTest(ModuleStoreNoSettings):
# Remap the namespace # Remap the namespace
target_location_namespace = Location("org", "course", "run", "category", "stubxblock") target_location_namespace = Location("org", "course", "run", "category", "stubxblock")
new_version = _import_module_and_update_references( new_version = _update_and_import_module(
self.xblock, self.xblock,
modulestore(), modulestore(),
999, 999,
...@@ -213,7 +213,7 @@ class RemapNamespaceTest(ModuleStoreNoSettings): ...@@ -213,7 +213,7 @@ class RemapNamespaceTest(ModuleStoreNoSettings):
# Remap the namespace # Remap the namespace
target_location_namespace = Location("org", "course", "run", "category", "stubxblock") target_location_namespace = Location("org", "course", "run", "category", "stubxblock")
new_version = _import_module_and_update_references( new_version = _update_and_import_module(
self.xblock, self.xblock,
modulestore(), modulestore(),
999, 999,
......
...@@ -42,6 +42,9 @@ def _export_drafts(modulestore, course_key, export_fs, xml_centric_course_key): ...@@ -42,6 +42,9 @@ def _export_drafts(modulestore, course_key, export_fs, xml_centric_course_key):
qualifiers={'category': {'$nin': DIRECT_ONLY_CATEGORIES}}, qualifiers={'category': {'$nin': DIRECT_ONLY_CATEGORIES}},
revision=ModuleStoreEnum.RevisionOption.draft_only revision=ModuleStoreEnum.RevisionOption.draft_only
) )
# Check to see if the returned draft modules have changes w.r.t. the published module.
# Only modules with changes will be exported into the /drafts directory.
draft_modules = [module for module in draft_modules if modulestore.has_changes(module)]
if draft_modules: if draft_modules:
draft_course_dir = export_fs.makeopendir(DRAFT_DIR) draft_course_dir = export_fs.makeopendir(DRAFT_DIR)
...@@ -153,20 +156,15 @@ class ExportManager(object): ...@@ -153,20 +156,15 @@ class ExportManager(object):
Perform the export given the parameters handed to this class at init. Perform the export given the parameters handed to this class at init.
""" """
with self.modulestore.bulk_operations(self.courselike_key): with self.modulestore.bulk_operations(self.courselike_key):
# depth = None: Traverses down the entire course structure.
# lazy = False: Loads and caches all block definitions during traversal for fast access later
# -and- to eliminate many round-trips to read individual definitions.
# Why these parameters? Because a course export needs to access all the course block information
# eventually. Accessing it all now at the beginning increases performance of the export.
fsm = OSFS(self.root_dir)
courselike = self.get_courselike()
export_fs = courselike.runtime.export_fs = fsm.makeopendir(self.target_dir)
root_courselike_dir = self.root_dir + '/' + self.target_dir
fsm = OSFS(self.root_dir)
root = lxml.etree.Element('unknown') # pylint: disable=no-member root = lxml.etree.Element('unknown') # pylint: disable=no-member
# export only the published content # export only the published content
with self.modulestore.branch_setting(ModuleStoreEnum.Branch.published_only, self.courselike_key): with self.modulestore.branch_setting(ModuleStoreEnum.Branch.published_only, self.courselike_key):
courselike = self.get_courselike()
export_fs = courselike.runtime.export_fs = fsm.makeopendir(self.target_dir)
# change all of the references inside the course to use the xml expected key type w/o version & branch # change all of the references inside the course to use the xml expected key type w/o version & branch
xml_centric_courselike_key = self.get_key() xml_centric_courselike_key = self.get_key()
adapt_references(courselike, xml_centric_courselike_key, export_fs) adapt_references(courselike, xml_centric_courselike_key, export_fs)
...@@ -176,6 +174,7 @@ class ExportManager(object): ...@@ -176,6 +174,7 @@ class ExportManager(object):
self.process_root(root, export_fs) self.process_root(root, export_fs)
# Process extra items-- drafts, assets, etc # Process extra items-- drafts, assets, etc
root_courselike_dir = self.root_dir + '/' + self.target_dir
self.process_extra(root, courselike, root_courselike_dir, xml_centric_courselike_key, export_fs) self.process_extra(root, courselike, root_courselike_dir, xml_centric_courselike_key, export_fs)
# Any last pass adjustments # Any last pass adjustments
...@@ -192,6 +191,11 @@ class CourseExportManager(ExportManager): ...@@ -192,6 +191,11 @@ class CourseExportManager(ExportManager):
) )
def get_courselike(self): def get_courselike(self):
# depth = None: Traverses down the entire course structure.
# lazy = False: Loads and caches all block definitions during traversal for fast access later
# -and- to eliminate many round-trips to read individual definitions.
# Why these parameters? Because a course export needs to access all the course block information
# eventually. Accessing it all now at the beginning increases performance of the export.
return self.modulestore.get_course(self.courselike_key, depth=None, lazy=False) return self.modulestore.get_course(self.courselike_key, depth=None, lazy=False)
def process_root(self, root, export_fs): def process_root(self, root, export_fs):
......
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