source: trunk/merengueproj/merengue/pluggable/__init__.py @ 5523

Revision 5523, 9.4 KB checked in by pmartin, 4 months ago (diff)

See #2292 #1 Refactor plugable/init

Line 
1# Copyright (c) 2010 by Yaco Sistemas
2#
3# This file is part of Merengue.
4#
5# Merengue is free software: you can redistribute it and/or modify
6# it under the terms of the GNU Lesser General Public License as published by
7# the Free Software Foundation, either version 3 of the License, or
8# (at your option) any later version.
9#
10# Merengue is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13# GNU Lesser General Public License for more details.
14#
15# You should have received a copy of the GNU Lesser General Public License
16# along with Merengue.  If not, see <http://www.gnu.org/licenses/>.
17from os import path
18
19
20from django.conf import settings
21from django.utils.translation import ugettext
22
23from south.signals import post_migrate
24from transmeta import get_fallback_fieldname
25
26from merengue.urlresolvers import get_url_default_lang
27from merengue.registry import register, have_registered_items
28from merengue.registry.items import RegistrableItem
29from merengue.registry.models import RegisteredItem
30from merengue.utils import is_last_application, classproperty
31
32
33class Plugin(RegistrableItem):
34    singleton = True
35    url_prefixes = ()
36    active_by_default = False
37
38    def get_url_prefixes(self):
39        prefixes = []
40        for url_prefix, url in self.url_prefixes:
41            prefix = url_prefix
42            if isinstance(url_prefix, dict):
43                prefix = url_prefix.get(get_url_default_lang())
44            prefixes.append((path.join(settings.BASE_URL[1:], prefix), url))
45
46        return prefixes
47
48    @classmethod
49    def get_category(cls):
50        return 'plugin'
51
52    @classproperty
53    @classmethod
54    def model(self):
55        from merengue.pluggable.models import RegisteredPlugin
56        return RegisteredPlugin
57
58    def _get_registered_items(self, item_classes):
59        for item_class in item_classes:
60            reg_item = RegisteredItem.objects.get_by_item_class(item_class)
61            yield reg_item.get_registry_item()
62
63    def get_actions(self):
64        return []  # to override in plugins
65
66    def get_actions_items(self):
67        return []  # to override in plugins
68
69    def get_blocks(self):
70        return []  # to override in plugins
71
72    def get_middlewares(self):
73        return []  # to override in plugins
74
75    def get_viewlets(self):
76        return []  # to override in plugins
77
78    def post_actions(self):
79        pass
80
81    def models(self):
82        return []  # to override in plugins
83
84    def section_models(self):
85        return []  # to override in plugins
86
87    def section_register_hook(self, site_related, model):
88        pass
89
90    def get_model_admins(self):
91        return []  # to override in plugins
92
93    def get_perms(self):
94        return []  # to override in plugins
95
96    def get_toolbar_panels(self):
97        return []  # to override in plugins
98
99    def get_section_prefixes(self):
100        return []  # to override in plugins
101
102    def post_install(self):
103        pass
104
105    def get_notifications(self):
106        return []  # to override in plugins
107
108    def get_blocks_items(self):
109        return self._get_registered_items(self.get_blocks())
110
111    def get_toolbar_panels_items(self):
112        return self._get_registered_items(self.get_toolbar_panels())
113
114    def get_viewlets_items(self):
115        return self._get_registered_items(self.get_viewlets())
116
117
118def register_plugin(plugin_dir):
119    from merengue.pluggable.models import RegisteredPlugin
120    from merengue.pluggable.utils import get_plugin_config, validate_plugin
121    plugin_config = get_plugin_config(plugin_dir)
122    if plugin_config:
123        validate_plugin(plugin_config)
124        try:
125            reg_plugin = RegisteredPlugin.objects.get_by_item_class(plugin_config)
126        except RegisteredPlugin.DoesNotExist:
127            reg_plugin = register(plugin_config)
128        plugin = reg_plugin.get_registry_item()
129        reg_plugin.name = getattr(plugin, 'name')
130        reg_plugin.directory_name = plugin_dir
131        reg_plugin.description = getattr(plugin, 'description', '')
132        reg_plugin.version = getattr(plugin, 'version', '')
133        reg_plugin.required_apps = getattr(plugin, 'required_apps',
134                                           None)
135        reg_plugin.required_plugins = getattr(plugin,
136                                              'required_plugins',
137                                              None)
138        reg_plugin.meta_info = {}
139        if hasattr(plugin, 'screenshot'):
140            reg_plugin.meta_info['screenshot'] = plugin.screenshot
141        reg_plugin.meta_info['actions'] = []
142        for action in plugin.get_actions():
143            reg_plugin.meta_info['actions'].append({'name': unicode(action.name), 'help_text': unicode(action.help_text)})
144        reg_plugin.meta_info['blocks'] = []
145        for block in plugin.get_blocks():
146            reg_plugin.meta_info['blocks'].append({'name': unicode(block.name), 'help_text': unicode(block.help_text)})
147        if plugin.get_model_admins():
148            reg_plugin.meta_info['has_own_admin'] = True
149        else:
150            reg_plugin.meta_info['has_own_admin'] = False
151        reg_plugin.meta_info['middlewares'] = []
152        for middleware in plugin.get_middlewares():
153            reg_plugin.meta_info['middlewares'].append(middleware)
154        reg_plugin.meta_info['section_models'] = []
155        for model, admin in plugin.section_models():
156            reg_plugin.meta_info['section_models'].append({'name': unicode(model._meta.verbose_name)})
157        reg_plugin.meta_info['viewlets'] = []
158        for viewlet in plugin.get_viewlets():
159            reg_plugin.meta_info['viewlets'].append({'name': unicode(viewlet.name), 'help_text': unicode(viewlet.help_text)})
160
161        if "notification" in settings.INSTALLED_APPS:
162            from notification.models import create_notice_type
163            for notification in plugin.get_notifications():
164                label, display, description = notification
165                create_notice_type(label, display, description)
166
167        reg_plugin.save()
168        return reg_plugin
169    return None
170
171
172def enable_active_plugins():
173    from merengue.pluggable.models import RegisteredPlugin
174    from merengue.pluggable.utils import enable_plugin, get_plugin_module_name, reload_models_cache
175    for plugin_registered in RegisteredPlugin.objects.actives():
176        enable_plugin(get_plugin_module_name(plugin_registered.directory_name))
177    reload_models_cache()
178
179
180def register_all_plugins(verbose=False):
181    from merengue.pluggable.models import RegisteredPlugin
182    from merengue.pluggable.utils import (get_plugin_directories, get_plugin_config,
183                                          reload_models_cache, remove_from_installed_apps,
184                                          clear_plugin_module_cache, get_plugin_module_name)
185    from merengue.pluggable.checker import mark_broken_plugin
186    try:
187        for plugin_dir in get_plugin_directories():
188            try:
189                if verbose:
190                    plugin_config = get_plugin_config(plugin_dir)
191                    if plugin_config:
192                        if not have_registered_items(plugin_config):
193                            print 'Registering new plugin %s...' % plugin_dir
194                        else:
195                            print 'Re-registering plugin %s...' % plugin_dir
196                    else:
197                        print 'Error walking to plugin %s.' % plugin_dir
198                register_plugin(plugin_dir)
199            except:
200                mark_broken_plugin(plugin_dir)
201                print 'Error registering %s plugin... go to next plugin.' % plugin_dir
202    finally:
203        for plugin in RegisteredPlugin.objects.inactives():
204            clear_plugin_module_cache(get_plugin_module_name(plugin.directory_name))
205            remove_from_installed_apps(plugin.directory_name)
206        reload_models_cache()
207
208
209def active_default_plugins(*args, **kwargs):
210    """ active default plugins and creates the portal menu in each language """
211    # Only want to run this signal after all application was migrated, but
212    # south have not a "post all migrations" signal.
213    # The workaround is "collab" have to be the last application migrated
214    if is_last_application(kwargs['app']):
215        # register required plugins
216        for plugin_dir in settings.REQUIRED_PLUGINS:
217            active_plugin_with_deps(plugin_dir)
218        # populate menu
219        from merengue.section.models import Menu
220        name_attr = get_fallback_fieldname('name')
221        attrs = {name_attr: 'Portal menu', 'slug': settings.MENU_PORTAL_SLUG}
222        try:
223            portal_menu = Menu.objects.get(slug=settings.MENU_PORTAL_SLUG)
224        except Menu.DoesNotExist:
225            # creating portal menu if does not exist
226            portal_menu = Menu.objects.create(**attrs)
227            for lang_code, lang_text in settings.LANGUAGES:
228                setattr(portal_menu, 'name_%s' % lang_code, ugettext('portal menu'))
229            portal_menu.save()
230
231
232def active_plugin_with_deps(plugin_dir):
233    """ active plugins with its dependences """
234    from merengue.pluggable.utils import install_plugin
235    registered_plugin = register_plugin(plugin_dir)
236    plugin = registered_plugin.get_registry_item()
237    for dep in getattr(plugin, 'required_plugins', []):
238        active_plugin_with_deps(dep)
239    registered_plugin.installed = True
240    registered_plugin.active = True
241    registered_plugin.save()
242    install_plugin(registered_plugin)
243
244
245post_migrate.connect(active_default_plugins)
Note: See TracBrowser for help on using the repository browser.