Start of ability to have plugins provide static resources!
authorChristopher Allan Webber <cwebber@dustycloud.org>
Thu, 16 May 2013 15:38:45 +0000 (10:38 -0500)
committerChristopher Allan Webber <cwebber@dustycloud.org>
Thu, 23 May 2013 18:33:07 +0000 (13:33 -0500)
Note I have not tested any of this yet ;)  But we're already on our way:
 - We've got docs
 - The hook is there

Lots to do still though.  But, progress! :)

This commit sponsored by Laura Arjona Reina.  Thanks larjona!

docs/source/pluginwriter/api.rst
mediagoblin/init/__init__.py
mediagoblin/tools/staticdirect.py

index 5e0568fd580d434fd16ac844ff9fd0230523f4e4..cd06cbc547e5d3fe2842d584686643db0919450a 100644 (file)
@@ -125,3 +125,22 @@ context... it is added to the actual context of each individual
 template render right before it is run!  Because of this you also can
 do some powerful and crazy things, such as checking the request object
 or other parts of the context before passing them on.
+
+
+Adding static resources
+-----------------------
+
+It's possible to add static resources for your plugin.  Say your
+plugin needs some special javascript and images... how to provide
+them?  Then how to access them?  MediaGoblin has a way!
+
+
+Attaching to the hook
++++++++++++++++++++++
+
+First, you need to register your plugin's resources with the hook.
+This is pretty easy actually: you just need to provide a function that
+passes back a PluginStatic object.
+
+.. automodule:: mediagoblin.tools.staticdirect
+   :members: PluginStatic
index d16027db62385cc2a5382493e1268b71ddcb23de..1eb9f1ba156bd328f83f78bde55614c4d0c9c506 100644 (file)
@@ -24,6 +24,7 @@ from mediagoblin import mg_globals
 from mediagoblin.mg_globals import setup_globals
 from mediagoblin.db.open import setup_connection_and_db_from_config, \
     check_db_migrations_current, load_models
+from mediagoblin.pluginapi import hook_runall
 from mediagoblin.tools.workbench import WorkbenchManager
 from mediagoblin.storage import storage_system_from_config
 
@@ -116,6 +117,12 @@ def get_staticdirector(app_config):
     direct_domains = {None: app_config['direct_remote_path'].strip()}
     direct_domains['theme'] = app_config['theme_web_path'].strip()
 
+    # Let plugins load additional paths
+    for plugin_static in hook_runall("static_setup"):
+        direct_domains[plugin_static['name']] = "%s/%s" % (
+            app_config['plugin_web_path'].rstrip('/'),
+            plugin_static['name'])
+
     return staticdirect.StaticDirect(
         direct_domains)
 
index 31abc566c3194e58c2b75717b26a78ef241b9636..ef8b20d083197792e22a67b51b2350ed75a55818 100644 (file)
@@ -61,3 +61,41 @@ class StaticDirect(object):
     def get(self, filepath, domain=None):
         return '%s/%s' % (
             self.domains[domain], filepath.lstrip('/'))
+
+
+class PluginStatic(object):
+    """Pass this into the ``'static_setup'`` hook to register your
+    plugin's static directory.
+
+    This has two mandatory attributes that you must pass in on class
+    init:
+     - name: this name will be both used for lookup in "urlgen" for
+       your plugin's static resources and for the subdirectory that
+       it'll be "mounted" to for serving via your web browser.  It
+       *MUST* be unique.  If writing a plugin bundled with MediaGoblin
+       please use the pattern 'coreplugin__foo' where 'foo' is your
+       plugin name.  All external plugins should use their modulename,
+       so if your plugin is 'mg_bettertags' you should also call this
+       name 'mg_bettertags'.
+     - file_path: the directory your plugin's static resources are
+       located in.  It's recommended that you use
+       pkg_resources.resource_filename() for this.
+
+    An example of using this::
+
+      from pkg_resources import resource_filename
+      from mediagoblin.tools.staticdirect import PluginStatic
+
+      hooks = {
+          'static_setup': lambda: PluginStatic(
+              'mg_bettertags',
+              resource_filename('mg_bettertags', 'static'))
+      }
+
+    """
+    def __init__(self, name, file_path):
+        self.name = name
+        self.file_path = file_path
+
+    def __call__(self):
+        return self