From 95b813473151d42609ec556b52ad3f5c8610d0d6 Mon Sep 17 00:00:00 2001
From: ichuang <ichuang@mit.edu>
Date: Thu, 17 Jan 2013 03:40:24 +0000
Subject: [PATCH] initial implementation of conditional_module; doesn't load
 dynamically yet

---
 common/lib/xmodule/setup.py                   |  1 +
 common/lib/xmodule/xmodule/capa_module.py     |  5 ++
 .../lib/xmodule/xmodule/conditional_module.py | 88 +++++++++++++++++++
 3 files changed, 94 insertions(+)
 create mode 100644 common/lib/xmodule/xmodule/conditional_module.py

diff --git a/common/lib/xmodule/setup.py b/common/lib/xmodule/setup.py
index 29227c31884..a1b059b8891 100644
--- a/common/lib/xmodule/setup.py
+++ b/common/lib/xmodule/setup.py
@@ -20,6 +20,7 @@ setup(
             "book = xmodule.backcompat_module:TranslateCustomTagDescriptor",
             "chapter = xmodule.seq_module:SequenceDescriptor",
             "combinedopenended = xmodule.combined_open_ended_module:CombinedOpenEndedDescriptor",
+            "conditional = xmodule.conditional_module:ConditionalDescriptor",
             "course = xmodule.course_module:CourseDescriptor",
             "customtag = xmodule.template_module:CustomTagDescriptor",
             "discuss = xmodule.backcompat_module:TranslateCustomTagDescriptor",
diff --git a/common/lib/xmodule/xmodule/capa_module.py b/common/lib/xmodule/xmodule/capa_module.py
index f33da6e3a43..01e67d9f8bd 100644
--- a/common/lib/xmodule/xmodule/capa_module.py
+++ b/common/lib/xmodule/xmodule/capa_module.py
@@ -398,6 +398,11 @@ class CapaModule(XModule):
 
         return False
 
+    def is_completed(self):
+        # used by conditional module
+        # return self.answer_available()
+        return self.lcp.done
+
     def answer_available(self):
         ''' Is the user allowed to see an answer?
         '''
diff --git a/common/lib/xmodule/xmodule/conditional_module.py b/common/lib/xmodule/xmodule/conditional_module.py
new file mode 100644
index 00000000000..c022c3742ac
--- /dev/null
+++ b/common/lib/xmodule/xmodule/conditional_module.py
@@ -0,0 +1,88 @@
+import logging
+
+from xmodule.x_module import XModule
+from xmodule.modulestore import Location
+from xmodule.seq_module import SequenceDescriptor
+
+log = logging.getLogger('mitx.' + __name__)
+
+class ConditionalModule(XModule):
+    '''
+    Blocks child module from showing unless certain conditions are met.
+
+    Example:
+        
+        <conditional condition="require_completed" required="tag/url_name1&tag/url_name2">
+            <video url_name="secret_video" />
+        </conditional>
+
+    '''
+
+    def __init__(self, system, location, definition, descriptor, instance_state=None, shared_state=None, **kwargs):
+        """
+        In addition to the normal XModule init, provide:
+        
+            self.required_module_list = list of (tag, url_name) tuples of modules required by this one.
+            self.condition            = string describing condition required
+
+        """
+        XModule.__init__(self, system, location, definition, descriptor, instance_state, shared_state, **kwargs)
+        self.contents = None
+        self.required_modules_list = [tuple(x.split('/',1)) for x in self.metadata.get('required','').split('&')]
+        self.condition = self.metadata.get('condition','')
+        log.debug('conditional module required=%s' % self.required_modules_list)
+
+    def _get_required_modules(self):
+        self.required_modules = []
+        for (tag, name) in self.required_modules_list:
+            loc = self.location.dict()
+            loc['category'] = tag
+            loc['name'] = name
+            module = self.system.get_module(loc)
+            self.required_modules.append(module)
+        log.debug('required_modules=%s' % (self.required_modules))
+
+    def is_condition_satisfied(self):
+        self._get_required_modules()
+
+        if self.condition=='require_completed':
+            # all required modules must be completed, as determined by
+            # the modules .is_completed() method
+            for module in self.required_modules:
+                if not hasattr(module, 'is_completed'):
+                    raise Exception('Error in conditional module: required module %s has no .is_completed() method' % module)
+                if not module.is_completed():
+                    log.debug('condition module: %s not completed' % module)
+                    return False
+                else:
+                    log.debug('condition module: %s IS completed' % module)
+            return True
+        else:
+            raise Exception('Error in conditional module: unknown condition "%s"' % self.condition)
+
+        return True
+
+    def get_html(self):
+        if not self.is_condition_satisfied():
+            context = {'module': self,
+                      }
+            return self.system.render_template('conditional_module.html', context)
+
+        if self.contents is None:
+            self.contents = [child.get_html() for child in self.get_display_items()]
+
+        # for now, just deal with one child
+        html = self.contents[0]
+        
+        log.debug('rendered conditional module %s' % str(self.location))
+
+        return html
+
+class ConditionalDescriptor(SequenceDescriptor):
+    module_class = ConditionalModule
+
+    filename_extension = "xml"
+
+    stores_state = True
+    has_score = False
+    
\ No newline at end of file
-- 
GitLab