Repository: django-cms/django-cms

Issue:
Plugin Context Processors should get the context passed too
Plugin Context Processors would be a lot more useful if they had access to the actual context. Or at the very least to the request.



Discussion:
This would be nice, but I'm not sure it's possible to do it cleanly in a backwards compatible way.  I guess it could be done as part of the 3.0 release.

The plugin context processors are defined by users, so adding an extra argument will break all existing plugin context processors.

Other options I could think of are 
- to create a new different type of plugin - but then there are two things to maintain, not nice
- to introspect each context processor to see how many arguments it takes and pass it the existing context if it takes that many arguments.  But that seems quite brittle and doesn't feel nice.

Maybe there's some other way that works well - any suggestions.

we can break this for 3.0


Resolving patch:
diff --git a/cms/plugin_processors.py b/cms/plugin_processors.py
--- a/cms/plugin_processors.py
+++ b/cms/plugin_processors.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 from django.utils.safestring import mark_safe
 
-def plugin_meta_context_processor(instance, placeholder):
+def plugin_meta_context_processor(instance, placeholder, context):
     return {
         'plugin_index': instance._render_meta.index, # deprecated template variable
         'plugin': {
@@ -18,4 +18,4 @@ def plugin_meta_context_processor(instance, placeholder):
     }
 
 def mark_safe_plugin_processor(instance, placeholder, rendered_content, original_context):
-    return mark_safe(rendered_content)
\ No newline at end of file
+    return mark_safe(rendered_content)
diff --git a/cms/plugin_rendering.py b/cms/plugin_rendering.py
--- a/cms/plugin_rendering.py
+++ b/cms/plugin_rendering.py
@@ -34,11 +34,12 @@ def __init__(self, dict, instance, placeholder, processors=None, current_app=Non
         if not processors:
             processors = []
         for processor in DEFAULT_PLUGIN_CONTEXT_PROCESSORS:
-            self.update(processor(instance, placeholder))
+            self.update(processor(instance, placeholder, self))
         for processor in iterload_objects(get_cms_setting('PLUGIN_CONTEXT_PROCESSORS')):
-            self.update(processor(instance, placeholder))
+            self.update(processor(instance, placeholder, self))
         for processor in processors:
-            self.update(processor(instance, placeholder))
+            self.update(processor(instance, placeholder, self))
+
 
 def render_plugin(context, instance, placeholder, template, processors=None, current_app=None):
     """
@@ -66,7 +67,7 @@ def render_plugins(plugins, context, placeholder, processors=None):
     Renders a collection of plugins with the given context, using the appropriate processors
     for a given placeholder name, and returns a list containing a "rendered content" string
     for each plugin.
-    
+
     This is the main plugin rendering utility function, use this function rather than
     Plugin.render_plugin().
     """
@@ -88,7 +89,7 @@ def render_dragables(plugins, slot, request):
 
 def render_placeholder(placeholder, context_to_copy, name_fallback="Placeholder"):
     """
-    Renders plugins for a placeholder on the given page using shallow copies of the 
+    Renders plugins for a placeholder on the given page using shallow copies of the
     given context, and returns a string containing the rendered output.
     """
     from cms.plugins.utils import get_plugins
@@ -103,7 +104,7 @@ def render_placeholder(placeholder, context_to_copy, name_fallback="Placeholder"
         template = None
     # Add extra context as defined in settings, but do not overwrite existing context variables,
     # since settings are general and database/template are specific
-    # TODO this should actually happen as a plugin context processor, but these currently overwrite 
+    # TODO this should actually happen as a plugin context processor, but these currently overwrite
     # existing context -- maybe change this order?
     slot = getattr(placeholder, 'slot', None)
     extra_context = {}


Test patch:
diff --git a/cms/tests/rendering.py b/cms/tests/rendering.py
--- a/cms/tests/rendering.py
+++ b/cms/tests/rendering.py
@@ -25,9 +25,12 @@ def sample_plugin_processor(instance, placeholder, rendered_content, original_co
     )
 
 
-def sample_plugin_context_processor(instance, placeholder):
-    content = 'test_plugin_context_processor_ok|' + instance.body + '|' + placeholder.slot
-    return {'test_plugin_context_processor': content}
+def sample_plugin_context_processor(instance, placeholder, original_context):
+    content = 'test_plugin_context_processor_ok|' + instance.body + '|' + \
+        placeholder.slot + '|' + original_context['original_context_var']
+    return {
+        'test_plugin_context_processor': content,
+    }
 
 
 class RenderingTestCase(SettingsOverrideTestCase):
@@ -158,7 +161,7 @@ def test_processors(self):
                 CMS_PLUGIN_PROCESSORS=('cms.tests.rendering.sample_plugin_processor',),
                 CMS_PLUGIN_CONTEXT_PROCESSORS=('cms.tests.rendering.sample_plugin_context_processor',),
         ):
-            def test_passed_plugin_context_processor(instance, placeholder):
+            def test_passed_plugin_context_processor(instance, placeholder, context):
                 return {'test_passed_plugin_context_processor': 'test_passed_plugin_context_processor_ok'}
 
             t = u'{% load cms_tags %}' + \
@@ -172,7 +175,7 @@ def test_passed_plugin_context_processor(instance, placeholder):
             r = "".join(c)
             self.assertEqual(r, u'1|' + self.test_data[
                 'text_main'] + '|test_passed_plugin_context_processor_ok|test_plugin_context_processor_ok|' +
-                                self.test_data['text_main'] + '|main|test_plugin_processor_ok|' + self.test_data[
+                                self.test_data['text_main'] + '|main|original_context_var_ok|test_plugin_processor_ok|' + self.test_data[
                                     'text_main'] + '|main|original_context_var_ok')
             plugin_rendering._standard_processors = {}
 
@@ -185,7 +188,6 @@ def test_placeholder(self):
         r = self.render(t, self.test_page)
         self.assertEqual(r, u'|' + self.test_data['text_main'] + '|')
 
-
     def test_placeholder_extra_context(self):
         t = u'{% load cms_tags %}{% placeholder "extra_context" %}'
         r = self.render(t, self.test_page4)