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

Revision 1816, 8.0 kB (checked in by JensDiemer, 5 months ago)

Chnage the way to get the plugin_name. The Problem was: self.class.name does not represent in every case the real plugin name! If a big plugin split the plugin methods in smaller file/classes and inherit directly from PyLucidBasePlugin?. e.g. the show_interals does this...
The right plugin name is needed for getting the right internal page files.

  • 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, plugin_name):
50        self.plugin_name = plugin_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, err:
175            if debug:
176                msg = err
177            else:   
178                msg = "Internal page '%s' not found!" % internal_page_name
179            self.page_msg.red(msg)
180            return "[%s]" % msg
181
182        self._add_js_css_data(internal_page_name)
183
184        html = self.__render(content, context, debug)
185
186        html = mark_safe(html) # turn djngo auto-escaping off
187        return html
188
189    def _render_template(self, internal_page_name, context, debug=False):
190        """
191        render a template and write it into the response object
192        """
193        html = self._get_rendered_template(internal_page_name, context, debug)
194        self.response.write(html)
195
196    def _render_string_template(self, template, context, debug=False):
197        """
198        Render a string-template with the given context.
199        Should be only used for developing. The normal way is: Use a internal
200        page for templates.
201        """
202        html = self.__render(template, context, debug)
203        self.response.write(html)
204
205    def __render(self, template, context, debug=False):
206        """
207        render the template string with the given context and returned it.
208        -debug the context, if debug is on.
209        """
210        html = render_string_template(template, context)
211
212        if debug:
213            self.response.write("<fieldset><legend>template debug:</legend>")
214
215            self.response.write("<legend>context:</legend>")
216            self.response.write("<pre>")
217            self.response.write(escape(pprint.pformat(context)))
218            self.response.write("</pre>")
219
220            self.response.write("<legend>template:</legend>")
221            self.response.write("<pre>")
222            self.response.write(escape(template))
223            self.response.write("</pre>")
224
225            if debug>1:
226                self.response.write("<legend>result html code:</legend>")
227                self.response.write("<pre>")
228                self.response.write(escape(html))
229                self.response.write("</pre>")
230
231            self.response.write("</fieldset>")
232
233        return html
234
235    def error(self, public_msg, debug_msg):
236        """
237        Display a error with page_msg.red().
238        Append debug_msg if self.request.debug is on
239        e.g.:
240            try:
241                ...do something...
242            except Exception, err:
243                return self.error(_("Wrong URL."), err)
244        """
245        msg = public_msg
246        if self.request.debug:
247            msg += " %s" % debug_msg
248
249        self.page_msg.red(msg)
250
Note: See TracBrowser for help on using the browser.