root/trunk/pylucid_project/PyLucid/system/BasePlugin.py

Revision 1804, 7.9 kB (checked in by JensDiemer, 42 hours ago)

Fixed: multiple additional stylesheets from plugins... ticket:233 http://www.pylucid.org/phpBB2/viewtopic.php?p=1361#1361

  • Property svn:eol-style set to LF
  • Property svn:executable set to *
  • Property svn:keywords set to Author Rev LastChangedDate
Line 
1# -*- coding: utf-8 -*-
2
3"""
4    PyLucid BasePlugin
5    ~~~~~~~~~~~~~~~~~~
6
7    The base Plugin object. Every Plugin can inherit.
8
9    e.g.:
10
11        from PyLucid.system.BasePlugin import PyLucidBasePlugin
12
13        class Bsp(PyLucidBasePlugin):
14            def __init__(self, *args, **kwargs):
15                super(Bsp, self).__init__(*args, **kwargs)
16
17    Know issues:
18        The page cache doesn't update, if the content changed.
19        So, PyLucid must reloaded (dev. server + fastCGI).
20        Never mind, becuase in future version, we don't save the internal
21        pages into the database ;)
22
23    Last commit info:
24    ~~~~~~~~~~~~~~~~~
25    $LastChangedDate$
26    $Rev$
27    $Author$
28
29    :copyleft: 2007 by the PyLucid team, see AUTHORS for more details.
30    :license: GNU GPL v3 or above, see LICENSE for more details.
31"""
32
33import os, pprint
34
35from django.conf import settings
36from django.utils.safestring import mark_safe
37
38from PyLucid.models import Plugin
39from PyLucid.tools.utils import escape
40from PyLucid.tools.content_processors import render_string_template
41from PyLucid.system.internal_page import InternalPage, InternalPageNotFound
42from PyLucid.system.plugin_import import get_plugin_config, \
43                                        get_plugin_version, debug_plugin_config
44
45
46
47class PyLucidBasePlugin(object):
48
49    def __init__(self, context, response):
50        self.plugin_name = self.__class__.__name__
51        self.internal_page = InternalPage(context, self.plugin_name)
52
53        self.request    = context["request"]
54        self.response   = response
55        self.context    = context
56
57        self.page_msg   = self.request.page_msg
58        self.URLs       = context["URLs"]
59        self.URLs.current_plugin = self.plugin_name
60
61        self.current_page = self.context["PAGE"]
62
63    def get_preferences(self, id=None):
64        """
65        returns the preferences from the database as a dict
66        """
67        preference = Plugin.objects.get_preferences(self.plugin_name, id)
68        return preference
69
70    def set_preferences(self, key, value, id=None):
71        """
72        set a new value to one preferences entry
73        """
74        user = self.request.user
75        data_dict = Plugin.objects.set_preferences(
76            self.plugin_name, key, value, user, id
77        )
78        return data_dict
79
80    def build_menu(self):
81        """
82        Build a simple menu for all plugin methods witch have a "menu_section"
83
84        Use the internal page template "admin_menu.plugin_menu" !
85
86        In the plugin config (plugin_manager_data) must be exist some meta
87        information for the menu:
88          "menu_section"     : The upper block name
89          "menu_description" : Link text (optional, otherwise method name used)
90
91        More info: http://pylucid.org/_goto/148/self-build_menu/
92        """
93        plugin = Plugin.objects.get(plugin_name=self.plugin_name)
94        plugin_config = get_plugin_config(
95            package_name = plugin.package_name,
96            plugin_name = self.plugin_name,
97        )
98        plugin_version = get_plugin_version(
99            package_name = plugin.package_name,
100            plugin_name = self.plugin_name,
101        )
102#        debug_plugin_config(self.page_msg, plugin_config)
103
104        plugin_manager_data = plugin_config.plugin_manager_data
105
106        menu_data = {}
107        for method_name, data in plugin_manager_data.iteritems():
108            if not "menu_section" in data:
109                continue
110
111            menu_section = data["menu_section"]
112
113            if not menu_section in menu_data:
114                menu_data[menu_section] = []
115
116            menu_data[menu_section].append(
117                {
118                    "link": self.URLs.methodLink(method_name),
119                    "description": data.get("menu_description", method_name),
120                }
121            )
122
123        self.context["PAGE"].title = "%s (%s)" % (
124            self.plugin_name.replace("_", " "), plugin_version
125        )
126
127        context = {"menu_data": menu_data,}
128
129        # Change the internal_page and use them from "admin_menu" plugin.
130        plugin_internal_page = self.internal_page
131        self.internal_page = InternalPage(
132            self.context, plugin_name="admin_menu"
133        )
134
135        self._render_template("plugin_menu", context)#, debug=False)
136
137        # change back to the original internal pages from the current plugin.
138        self.internal_page = plugin_internal_page
139
140
141    def _add_js_css_data(self, internal_page_name):
142        """
143        insert the additional JavaScript and StyleSheet data into the global
144        context.
145        page_style.replace_add_data() puts the file links into the page.
146        """
147        def is_added(slug_list, url):
148            for entry in slug_list:
149                if entry["url"] == url:
150                    return True
151            return False
152           
153        for slug in ("js", "css"):
154            url = self.internal_page.get_url(internal_page_name, slug)
155            if url == None:
156                continue
157           
158            slug_list = self.context["%s_data" % slug]
159            if is_added(slug_list, url):
160                # The same url has been added in the past -> skip
161                continue
162                       
163            slug_list.append({
164                "plugin_name": self.plugin_name,
165                "url": url,
166            })
167
168    def _get_rendered_template(self, internal_page_name, context, debug=False):
169        """
170        return a rendered internal page
171        """
172        try:
173            content = self.internal_page.get_content(internal_page_name, "html")
174        except InternalPageNotFound:
175            msg = "Internal page '%s' not found!" % internal_page_name
176            self.page_msg.red(msg)
177            return "[%s]" % msg
178
179        self._add_js_css_data(internal_page_name)
180
181        html = self.__render(content, context, debug)
182
183        html = mark_safe(html) # turn djngo auto-escaping off
184        return html
185
186    def _render_template(self, internal_page_name, context, debug=False):
187        """
188        render a template and write it into the response object
189        """
190        html = self._get_rendered_template(internal_page_name, context, debug)
191        self.response.write(html)
192
193    def _render_string_template(self, template, context, debug=False):
194        """
195        Render a string-template with the given context.
196        Should be only used for developing. The normal way is: Use a internal
197        page for templates.
198        """
199        html = self.__render(template, context, debug)
200        self.response.write(html)
201
202    def __render(self, template, context, debug=False):
203        """
204        render the template string with the given context and returned it.
205        -debug the context, if debug is on.
206        """
207        html = render_string_template(template, context)
208
209        if debug:
210            self.response.write("<fieldset><legend>template debug:</legend>")
211
212            self.response.write("<legend>context:</legend>")
213            self.response.write("<pre>")
214            self.response.write(escape(pprint.pformat(context)))
215            self.response.write("</pre>")
216
217            self.response.write("<legend>template:</legend>")
218            self.response.write("<pre>")
219            self.response.write(escape(template))
220            self.response.write("</pre>")
221
222            if debug>1:
223                self.response.write("<legend>result html code:</legend>")
224                self.response.write("<pre>")
225                self.response.write(escape(html))
226                self.response.write("</pre>")
227
228            self.response.write("</fieldset>")
229
230        return html
231
232    def error(self, public_msg, debug_msg):
233        """
234        Display a error with page_msg.red().
235        Append debug_msg if self.request.debug is on
236        e.g.:
237            try:
238                ...do something...
239            except Exception, err:
240                return self.error(_("Wrong URL."), err)
241        """
242        msg = public_msg
243        if self.request.debug:
244            msg += " %s" % debug_msg
245
246        self.page_msg.red(msg)
247
Note: See TracBrowser for help on using the browser.