819fac2d7845e0568044d2b60a02fe9026ef098a
[mediagoblin.git] / docs / source / pluginwriter / api.rst
1 .. MediaGoblin Documentation
2
3 Written in 2013 by MediaGoblin contributors
4
5 To the extent possible under law, the author(s) have dedicated all
6 copyright and related and neighboring rights to this software to
7 the public domain worldwide. This software is distributed without
8 any warranty.
9
10 You should have received a copy of the CC0 Public Domain
11 Dedication along with this software. If not, see
12 <http://creativecommons.org/publicdomain/zero/1.0/>.
13
14 .. _plugin-api-chapter:
15
16 ==========
17 Plugin API
18 ==========
19
20 This documents the general plugin API.
21
22 Please note, at this point OUR PLUGIN HOOKS MAY AND WILL CHANGE.
23 Authors are encouraged to develop plugins and work with the
24 MediaGoblin community to keep them up to date, but this API will be a
25 moving target for a few releases.
26
27 Please check the :ref:`release-notes` for updates!
28
29 :mod:`pluginapi` Module
30 -----------------------
31
32 .. automodule:: mediagoblin.tools.pluginapi
33 :members: get_config, register_routes, register_template_path,
34 register_template_hooks, get_hook_templates,
35 hook_handle, hook_runall, hook_transform
36
37 Configuration
38 -------------
39
40 Your plugin may define its own configuration defaults.
41
42 Simply add to the directory of your plugin a config_spec.ini file. An
43 example might look like::
44
45 [plugin_spec]
46 some_string = string(default="blork")
47 some_int = integer(default=50)
48
49 This means that when people enable your plugin in their config you'll
50 be able to provide defaults as well as type validation.
51
52
53 Context Hooks
54 -------------
55
56 View specific hooks
57 +++++++++++++++++++
58
59 You can hook up to almost any template called by any specific view
60 fairly easily. As long as the view directly or indirectly uses the
61 method ``render_to_response`` you can access the context via a hook
62 that has a key in the format of the tuple::
63
64 (view_symbolic_name, view_template_path)
65
66 Where the "view symbolic name" is the same parameter used in
67 ``request.urlgen()`` to look up the view. So say we're wanting to add
68 something to the context of the user's homepage. We look in
69 mediagoblin/user_pages/routing.py and see::
70
71 add_route('mediagoblin.user_pages.user_home',
72 '/u/<string:user>/',
73 'mediagoblin.user_pages.views:user_home')
74
75 Aha! That means that the name is ``mediagoblin.user_pages.user_home``.
76 Okay, so then we look at the view at the
77 ``mediagoblin.user_pages.user_home`` method::
78
79 @uses_pagination
80 def user_home(request, page):
81 # [...] whole bunch of stuff here
82 return render_to_response(
83 request,
84 'mediagoblin/user_pages/user.html',
85 {'user': user,
86 'user_gallery_url': user_gallery_url,
87 'media_entries': media_entries,
88 'pagination': pagination})
89
90 Nice! So the template appears to be
91 ``mediagoblin/user_pages/user.html``. Cool, that means that the key
92 is::
93
94 ("mediagoblin.user_pages.user_home",
95 "mediagoblin/user_pages/user.html")
96
97 The context hook uses ``hook_transform()`` so that means that if we're
98 hooking into it, our hook will both accept one argument, ``context``,
99 and should return that modified object, like so::
100
101 def add_to_user_home_context(context):
102 context['foo'] = 'bar'
103 return context
104
105 hooks = {
106 ("mediagoblin.user_pages.user_home",
107 "mediagoblin/user_pages/user.html"): add_to_user_home_context}
108
109
110 Global context hooks
111 ++++++++++++++++++++
112
113 If you need to add something to the context of *every* view, it is not
114 hard; there are two hooks hook that also uses hook_transform (like the
115 above) but make available what you are providing to *every* view.
116
117 Note that there is a slight, but critical, difference between the two.
118
119 The most general one is the ``'template_global_context'`` hook. This
120 one is run only once, and is read into the global context... all views
121 will get access to what are in this dict.
122
123 The slightly more expensive but more powerful one is
124 ``'template_context_prerender'``. This one is not added to the global
125 context... it is added to the actual context of each individual
126 template render right before it is run! Because of this you also can
127 do some powerful and crazy things, such as checking the request object
128 or other parts of the context before passing them on.
129
130
131 Adding static resources
132 -----------------------
133
134 It's possible to add static resources for your plugin. Say your
135 plugin needs some special javascript and images... how to provide
136 them? Then how to access them? MediaGoblin has a way!
137
138
139 Attaching to the hook
140 +++++++++++++++++++++
141
142 First, you need to register your plugin's resources with the hook.
143 This is pretty easy actually: you just need to provide a function that
144 passes back a PluginStatic object.
145
146 .. autoclass:: mediagoblin.tools.staticdirect.PluginStatic
147
148
149 Running plugin assetlink
150 ++++++++++++++++++++++++
151
152 In order for your plugin assets to be properly served by MediaGoblin,
153 your plugin's asset directory needs to be symlinked into the directory
154 that plugin assets are served from. To set this up, run::
155
156 ./bin/gmg assetlink
157
158
159 Using staticdirect
160 ++++++++++++++++++
161
162 Once you have this, you will want to be able to of course link to your
163 assets! MediaGoblin has a "staticdirect" tool; you want to use this
164 like so in your templates::
165
166 staticdirect("css/monkeys.css", "mystaticname")
167
168 Replace "mystaticname" with the name you passed to PluginStatic. The
169 staticdirect method is, for convenience, attached to the request
170 object, so you can access this in your templates like:
171
172 .. code-block:: html
173
174 <img alt="A funny bunny"
175 src="{{ request.staticdirect('images/funnybunny.png', 'mystaticname') }}" />