| 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 | |
|---|
| 33 | import os, pprint |
|---|
| 34 | |
|---|
| 35 | from django.conf import settings |
|---|
| 36 | from django.utils.safestring import mark_safe |
|---|
| 37 | |
|---|
| 38 | from PyLucid.models import Plugin |
|---|
| 39 | from PyLucid.tools.utils import escape |
|---|
| 40 | from PyLucid.tools.content_processors import render_string_template |
|---|
| 41 | from PyLucid.system.internal_page import InternalPage, InternalPageNotFound |
|---|
| 42 | from PyLucid.system.plugin_import import get_plugin_config, \ |
|---|
| 43 | get_plugin_version, debug_plugin_config |
|---|
| 44 | |
|---|
| 45 | |
|---|
| 46 | |
|---|
| 47 | class 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 | |
|---|