* Finally implemented a simple per-page data storage mechanism for plugins,
[ikiwiki] / doc / todo / plugin_data_storage.mdwn
1 ikiwiki currently stores some key data in .ikiwiki/index. Some plugins need a
2 way to store additional data, and ideally it would be something managed by
3 ikiwiki instead of ad-hoc because:
4
5 * consistency is good
6 * ikiwiki knows when a page is removed and can stop storing data for that
7   page; plugins have to go to some lengths to track that and remove their
8   data
9 * it's generally too much code and work to maintain a separate data store
10
11 The aggregate plugin is a use-case: of 324 lines, 70 are data storage and
12 another 10 handle deletion. Also, it's able to use a format very like
13 ikiwiki's, but it does need to store some lists in there, which complicates
14 it some and means that a very naive translation between a big per-page hash
15 and the .index won't be good enough.
16
17 The current ikiwiki index format is not very flexible, although it is at
18 least fairly easy and inexpensive to parse as well as hand-edit.
19
20 Would this do: ?
21
22 * Plugins can register savestate and loadstate hooks. The hook id is the
23   key used in the index file that the hook handles.
24 * loadstate hooks are called and passed a list of all values for a page
25   that for the registered key, and the page name, and should store the data
26   somewhere
27 * savestate hooks are called and passed a page, and should return a list of 
28   all values for that key for that page
29 * If they need anything more complex than a list of values, they will need
30   to encode it somehow in the list.
31
32 Hmm, that's potentially a lot of function calls per page eave load/save
33 though.. For less function calls, only call each hook *once* per load/save,
34 and it is passed/returns a big hash of pages and the values for each page.
35 (Which probably means `%state=@_` for load and `return %state` for save.)
36
37 It may also be better to just punt on lists, and require plugins that need
38 even lists to encode them. Especially since in many cases, `join(" ", @list)`
39 will do. Er hmm, if I do that though, I'm actually back to a big global
40 %page_data that plugins can just toss data into, arn't I? So maybe that's
41 %the right approach after all, hmm.. Except that needing to decode/encode list
42 data all the time when using it would quite suck, so no, let's not do that.
43
44 Note that for the aggregate plugin to use this, it will need some changes:
45
46 * guid data will need to be stored as part of the data for the page
47   that was aggregated from that guid. Except, expired pages don't exit, but
48   still have guid data to store. Hmm. I suppose the guid data could be
49   considered to be associated with the page that contains the aggregate
50   directive then.
51 * All feeds will need to be marked as removable in loadstate, and only
52   unmarked if seen in preprocess. Then savestate will need to not only
53   remove any feeds still marked as such, but do the unlinking of pages
54   aggregated from them too.
55
56 If I do this, I might as well also:
57
58 * Change the link= link= stuff to just links=link+link etc.
59 * Change the delimiter from space to comma; commas are rare in index files,
60   so less ugly escaped delimiters to deal with.
61
62 --- 
63
64 The [[plugins/calendar]] plugin could use plugin data storage to record
65 which pages have a calendar for the current time. Then ensure they are
66 rebuilt at least once a day. Currently, it needs a cron job to rebuild
67 the *whole* wiki every day; with this enhancement, the cron job would only
68 rebuild the few pages that really need it.
69
70
71 --- 
72
73 New design:
74
75 `%Ikiwiki::state` is an exported hash that stores per-page state.
76 Set with `$state{$page}{id}{key}=$value`. The `id` is the same `id` passed
77 to `hook()`.
78
79 This is stored in the index like:
80
81 src=foo.mdwn dest=bar.mdwn id_key=value [...]
82
83 The underscore ensures that there's no conflict with ikiwiki's own
84 state variables. (Note that `id` and `key` need to be encoded here.)
85
86 Plugins are reponsible for deleting old state info, though ikiwiki will
87 handle deleting it if a page is removed.
88
89 Ikiwiki needs to know when it can drop state for plugins that are no longer
90 enabled. This is done via `hook()` -- if a plugin registers a hook
91 ikiwiki knows it's still active, and preserves the state for the hook id.
92 If not, that state will be dropped.
93
94 [[done]]!! Now to use it..