1Wiki::Toolkit(3)      User Contributed Perl Documentation     Wiki::Toolkit(3)
2
3
4

NAME

6       Wiki::Toolkit - A toolkit for building Wikis.
7

DESCRIPTION

9       Helps you develop Wikis quickly by taking care of the boring bits for
10       you.  You will still need to write some code - this isn't an instant
11       Wiki.
12

SYNOPSIS

14         # Set up a wiki object with an SQLite storage backend, and an
15         # inverted index/DB_File search backend.  This store/search
16         # combination can be used on systems with no access to an actual
17         # database server.
18
19         my $store     = Wiki::Toolkit::Store::SQLite->new(
20             dbname => "/home/wiki/store.db" );
21         my $indexdb   = Search::InvertedIndex::DB::DB_File_SplitHash->new(
22             -map_name  => "/home/wiki/indexes.db",
23             -lock_mode => "EX" );
24         my $search    = Wiki::Toolkit::Search::SII->new(
25             indexdb => $indexdb );
26
27         my $wiki      = Wiki::Toolkit->new( store     => $store,
28                                             search    => $search );
29
30         # Do all the CGI stuff.
31         my $q      = CGI->new;
32         my $action = $q->param("action");
33         my $node   = $q->param("node");
34
35         if ($action eq 'display') {
36             my $raw    = $wiki->retrieve_node($node);
37             my $cooked = $wiki->format($raw);
38             print_page(node    => $node,
39                        content => $cooked);
40         } elsif ($action eq 'preview') {
41             my $submitted_content = $q->param("content");
42             my $preview_html      = $wiki->format($submitted_content);
43             print_editform(node    => $node,
44                            content => $submitted_content,
45                            preview => $preview_html);
46         } elsif ($action eq 'commit') {
47             my $submitted_content = $q->param("content");
48             my $cksum = $q->param("checksum");
49             my $written = $wiki->write_node($node, $submitted_content, $cksum);
50             if ($written) {
51                 print_success($node);
52             } else {
53                 handle_conflict($node, $submitted_content);
54             }
55         }
56

METHODS

58       new
59             # Set up store, search and formatter objects.
60             my $store     = Wiki::Toolkit::Store::SQLite->new(
61                 dbname => "/home/wiki/store.db" );
62             my $indexdb   = Search::InvertedIndex::DB::DB_File_SplitHash->new(
63                 -map_name  => "/home/wiki/indexes.db",
64                 -lock_mode => "EX" );
65             my $search    = Wiki::Toolkit::Search::SII->new(
66                 indexdb => $indexdb );
67             my $formatter = My::HomeMade::Formatter->new;
68
69             my $wiki = Wiki::Toolkit->new(
70                 store     => $store,     # mandatory
71                 search    => $search,    # defaults to undef
72                 formatter => $formatter  # defaults to something suitable
73             );
74
75           "store" must be an object of type "Wiki::Toolkit::Store::*" and
76           "search" if supplied must be of type "Wiki::Toolkit::Search::*"
77           (though this isn't checked yet - FIXME). If "formatter" isn't
78           supplied, it defaults to an object of class
79           Wiki::Toolkit::Formatter::Default.
80
81           You can get a searchable Wiki up and running on a system without an
82           actual database server by using the SQLite storage backend with the
83           SII/DB_File search backend - cut and paste the lines above for a
84           quick start, and see Wiki::Toolkit::Store::SQLite,
85           Wiki::Toolkit::Search::SII, and
86           Search::InvertedIndex::DB::DB_File_SplitHash when you want to learn
87           the details.
88
89           "formatter" can be any object that behaves in the right way; this
90           essentially means that it needs to provide a "format" method which
91           takes in raw text and returns the formatted version. See
92           Wiki::Toolkit::Formatter::Default for a simple example. Note that
93           you can create a suitable object from a sub very quickly by using
94           Test::MockObject like so:
95
96             my $formatter = Test::MockObject->new();
97             $formatter->mock( 'format', sub { my ($self, $raw) = @_;
98                                               return uc( $raw );
99                                             } );
100
101           I'm not sure whether to put this in the module or not - it'd let
102           you just supply a sub instead of an object as the formatter, but it
103           feels wrong to be using a Test::* module in actual code.
104
105       retrieve_node
106             my $content = $wiki->retrieve_node($node);
107
108             # Or get additional data about the node as well.
109             my %node = $wiki->retrieve_node("HomePage");
110             print "Current Version: " . $node{version};
111
112             # Maybe we stored some of our own custom metadata too.
113             my $categories = $node{metadata}{category};
114             print "Categories: " . join(", ", @$categories);
115             print "Postcode: $node{metadata}{postcode}[0]";
116
117             # Or get an earlier version:
118             my %node = $wiki->retrieve_node( name    => "HomePage",
119                                              version => 2,
120                                             );
121             print $node{content};
122
123           In scalar context, returns the current (raw Wiki language) contents
124           of the specified node. In list context, returns a hash containing
125           the contents of the node plus additional data:
126
127           last_modified
128           version
129           checksum
130           metadata - a reference to a hash containing any caller-supplied
131           metadata sent along the last time the node was written
132
133           The "node" parameter is mandatory. The "version" parameter is
134           optional and defaults to the newest version. If the node hasn't
135           been created yet, it is considered to exist but be empty (this
136           behaviour might change).
137
138           Note on metadata - each hash value is returned as an array ref,
139           even if that type of metadata only has one value.
140
141       moderate_node
142             my $ok = $wiki->moderate_node(name => $node, version => $version);
143
144           Marks the given version of the node as moderated. If this is the
145           highest moderated version, then update the node's contents to hold
146           this version.
147
148       set_node_moderation
149             my $ok = $wiki->set_node_moderation(name => $node, required => $required);
150
151           Sets if a node requires moderation or not.  (Moderation is required
152           when $required is true).
153
154           When moderation is required, new versions of a node will sit about
155           until they're tagged as moderated, when they will become the new
156           node.
157
158       rename_node
159             my $ok = $wiki->rename_node(old_name => $old_name, new_name => $new_name, create_new_versions => $create_new_versions );
160
161           Renames a node, updating any references to it as required.
162
163           Uses the internal_links table to identify the nodes that link to
164           this one, and re-writes any wiki links in these to point to the new
165           name. If required, it can mark these updates to other pages as a
166           new version.
167
168       verify_checksum
169             my $ok = $wiki->verify_checksum($node, $checksum);
170
171           Sees whether your checksum is current for the given node. Returns
172           true if so, false if not.
173
174           NOTE: Be aware that when called directly and without locking, this
175           might not be accurate, since there is a small window between the
176           checking and the returning where the node might be changed, so
177           don't rely on it for safe commits; use "write_node" for that. It
178           can however be useful when previewing edits, for example.
179
180       list_backlinks
181             # List all nodes that link to the Home Page.
182             my @links = $wiki->list_backlinks( node => "Home Page" );
183
184       list_dangling_links
185             # List all nodes that have been linked to from other nodes but don't
186             # yet exist.
187             my @links = $wiki->list_dangling_links;
188
189           Each node is returned once only, regardless of how many other nodes
190           link to it.
191
192       list_all_nodes
193             my @nodes = $wiki->list_all_nodes;
194
195           Returns a list containing the name of every existing node.  The
196           list won't be in any kind of order; do any sorting in your calling
197           script.
198
199       list_nodes_by_metadata
200             # All documentation nodes.
201             my @nodes = $wiki->list_nodes_by_metadata(
202                 metadata_type  => "category",
203                 metadata_value => "documentation",
204                 ignore_case    => 1,   # optional but recommended (see below)
205             );
206
207             # All pubs in Hammersmith.
208             my @pubs = $wiki->list_nodes_by_metadata(
209                 metadata_type  => "category",
210                 metadata_value => "Pub",
211             );
212             my @hsm  = $wiki->list_nodes_by_metadata(
213                 metadata_type  => "category",
214                 metadata_value  => "Hammersmith",
215             );
216             my @results = my_l33t_method_for_ANDing_arrays( \@pubs, \@hsm );
217
218           Returns a list containing the name of every node whose caller-
219           supplied metadata matches the criteria given in the parameters.
220
221           By default, the case-sensitivity of both "metadata_type" and
222           "metadata_value" depends on your database - if it will return rows
223           with an attribute value of "Pubs" when you asked for "pubs", or
224           not.  If you supply a true value to the "ignore_case" parameter,
225           then you can be sure of its being case-insensitive.  This is
226           recommended.
227
228           If you don't supply any criteria then you'll get an empty list.
229
230           This is a really really really simple way of finding things; if you
231           want to be more complicated then you'll need to call the method
232           multiple times and combine the results yourself, or write a plugin.
233
234       list_nodes_by_missing_metadata Returns nodes where either the metadata
235       doesn't exist, or is blank
236           Unlike list_nodes_by_metadata(), the metadata value is optional
237           (the metadata type is required).
238
239             # All nodes missing documentation
240             my @nodes = $store->list_nodes_by_missing_metadata(
241                 metadata_type  => "category",
242                 metadata_value => "documentation",
243                 ignore_case    => 1,   # optional but recommended (see below)
244             );
245
246             # All nodes which don't have a latitude defined
247             my @nodes = $store->list_nodes_by_missing_metadata(
248                 metadata_type  => "latitude"
249             );
250
251       list_recent_changes
252           This is documented in Wiki::Toolkit::Store::Database; see there for
253           parameters and return values.  All parameters are passed through
254           directly to the store object, so, for example,
255
256             my @nodes = $wiki->list_recent_changes( days => 7 );
257
258           does exactly the same thing as
259
260             my @nodes = $wiki->store->list_recent_changes( days => 7 );
261
262       list_unmoderated_nodes
263             my @nodes = $wiki->list_unmoderated_nodes();
264             my @nodes = $wiki->list_unmoderated_nodes(
265                                                           only_where_latest => 1
266                                                       );
267
268             $nodes[0]->{'name'}              # The name of the node
269             $nodes[0]->{'node_id'}           # The id of the node
270             $nodes[0]->{'version'}           # The version in need of moderation
271             $nodes[0]->{'moderated_version'} # The newest moderated version
272
273             Fetches details of all the node versions that require moderation (id,
274              name, version, and latest moderated version).
275
276             If only_where_latest is set, then only the latest version of nodes where
277              the latest version needs moderating are returned.
278             Otherwise, all node versions (including old ones, and possibly multiple
279              per node) are returned.
280
281       list_node_all_versions
282             my @versions = $wiki->list_node_all_versions("HomePage");
283
284             my @versions = $wiki->list_node_all_versions(
285                                                           name => 'HomePage',
286                                                           with_content => 1,
287                                                           with_metadata => 0
288                            );
289
290           Returns all the versions of a node, optionally including the
291           content and metadata, as an array of hashes (newest versions
292           first).
293
294       list_last_version_before List the last version of every node before a
295       given date. If no version existed before that date, will return undef
296       for version. Returns a hash of id, name, version and date
297               my @nv = $wiki->list_last_version_before('2007-01-02 10:34:11')
298               foreach my $data (@nv) {
299
300               }
301
302       node_exists
303             my $ok = $wiki->node_exists( "Wombat Defenestration" );
304
305             # or ignore case - optional but recommended
306             my $ok = $wiki->node_exists(
307                                          name        => "monkey brains",
308                                          ignore_case => 1,
309                                        );
310
311           Returns true if the node has ever been created (even if it is
312           currently empty), and false otherwise.
313
314           By default, the case-sensitivity of "node_exists" depends on your
315           store backend.  If you supply a true value to the "ignore_case"
316           parameter, then you can be sure of its being case-insensitive.
317           This is recommended.
318
319       node_required_moderation
320             my $needs = $wiki->node_required_moderation( "Wombat Defenestration" );
321
322           Returns true if the node exists and requires moderation, and false
323           otherwise.
324
325       delete_node
326             $wiki->delete_node( name => "Home Page", version => 15 );
327
328           "version" is optional.  If it is supplied then only that version of
329           the node will be deleted.  Otherwise the node and all its history
330           will be completely deleted.
331
332           Doesn't do any locking though - to fix? You probably don't want to
333           let anyone except Wiki admins call this. You may not want to use it
334           at all.
335
336           Croaks on error, silently does nothing if the node or version
337           doesn't exist, returns true if no error.
338
339       search_nodes
340             # Find all the nodes which contain the word 'expert'.
341             my %results = $wiki->search_nodes('expert');
342
343           Returns a (possibly empty) hash whose keys are the node names and
344           whose values are the scores in some kind of relevance-scoring
345           system I haven't entirely come up with yet. For OR searches, this
346           could initially be the number of terms that appear in the node,
347           perhaps.
348
349           Defaults to AND searches (if $and_or is not supplied, or is
350           anything other than "OR" or "or").
351
352           Searches are case-insensitive.
353
354           Croaks if you haven't defined a search backend.
355
356       supports_phrase_searches
357             if ( $wiki->supports_phrase_searches ) {
358                 return $wiki->search_nodes( '"fox in socks"' );
359             }
360
361           Returns true if your chosen search backend supports phrase
362           searching, and false otherwise.
363
364       supports_fuzzy_searches
365             if ( $wiki->supports_fuzzy_searches ) {
366                 return $wiki->fuzzy_title_match( 'Kings Cross, St Pancreas' );
367             }
368
369           Returns true if your chosen search backend supports fuzzy title
370           searching, and false otherwise.
371
372       fuzzy_title_match
373           NOTE: This section of the documentation assumes you are using a
374           search engine which supports fuzzy matching. (See above.) The
375           Wiki::Toolkit::Search::DBIxFTS backend in particular does not.
376
377             $wiki->write_node( "King's Cross St Pancras", "A station." );
378             my %matches = $wiki->fuzzy_title_match( "Kings Cross St. Pancras" );
379
380           Returns a (possibly empty) hash whose keys are the node names and
381           whose values are the scores in some kind of relevance-scoring
382           system I haven't entirely come up with yet.
383
384           Note that even if an exact match is found, any other similar enough
385           matches will also be returned. However, any exact match is
386           guaranteed to have the highest relevance score.
387
388           The matching is done against "canonicalised" forms of the search
389           string and the node titles in the database: stripping vowels,
390           repeated letters and non-word characters, and lowercasing.
391
392           Croaks if you haven't defined a search backend.
393
394       register_plugin
395             my $plugin = Wiki::Toolkit::Plugin::Foo->new;
396             $wiki->register_plugin( plugin => $plugin );
397
398           Registers the plugin with the wiki as one that needs to be informed
399           when we write a node.
400
401           If the plugin "isa" Wiki::Toolkit::Plugin, calls the methods set up
402           by that parent class to let it know about the backend store, search
403           and formatter objects.
404
405           Finally, calls the plugin class's "on_register" method, which
406           should be used to check tables are set up etc. Note that because of
407           the order these things are done in, "on_register" for
408           Wiki::Toolkit::Plugin subclasses can use the "datastore", "indexer"
409           and "formatter" methods as it needs to.
410
411       get_registered_plugins
412             my @plugins = $wiki->get_registered_plugins;
413
414           Returns an array of plugin objects.
415
416       write_node
417             my $written = $wiki->write_node($node, $content, $checksum, \%metadata, $requires_moderation);
418             if ($written) {
419                 display_node($node);
420             } else {
421                 handle_conflict();
422             }
423
424           Writes the specified content into the specified node in the backend
425           storage; and indexes/reindexes the node in the search indexes (if a
426           search is set up); calls "post_write" on any registered plugins.
427
428           Note that you can blank out a node without deleting it by passing
429           the empty string as $content, if you want to.
430
431           If you expect the node to already exist, you must supply a
432           checksum, and the node is write-locked until either your checksum
433           has been proved old, or your checksum has been accepted and your
434           change committed.  If no checksum is supplied, and the node is
435           found to already exist and be nonempty, a conflict will be raised.
436
437           The first two parameters are mandatory, the others optional. If you
438           want to supply metadata but have no checksum (for a newly-created
439           node), supply a checksum of "undef".
440
441           The final parameter, $requires_moderation (which defaults to
442           false), is ignored except on new nodes. For existing nodes, use
443           $wiki->toggle_node_moderation to change the node moderation flag.
444
445           Returns the version of the updated node on success, 0 on conflict,
446           croaks on error.
447
448           Note on the metadata hashref: Any data in here that you wish to
449           access directly later must be a key-value pair in which the value
450           is either a scalar or a reference to an array of scalars.  For
451           example:
452
453             $wiki->write_node( "Calthorpe Arms", "nice pub", $checksum,
454                                { category => [ "Pubs", "Bloomsbury" ],
455                                  postcode => "WC1X 8JR" } );
456
457             # and later
458
459             my @nodes = $wiki->list_nodes_by_metadata(
460                 metadata_type  => "category",
461                 metadata_value => "Pubs"             );
462
463           For more advanced usage (passing data through to registered
464           plugins) you may if you wish pass key-value pairs in which the
465           value is a hashref or an array of hashrefs. The data in the
466           hashrefs will not be stored as metadata; it will be checksummed and
467           the checksum will be stored instead. Such data can only be accessed
468           via plugins.
469
470       format
471             my $cooked = $wiki->format($raw, $metadata);
472
473           Passed straight through to your chosen formatter object. You do not
474           have to supply the $metadata hashref, but if your formatter allows
475           node metadata to affect the rendering of the node then you will
476           want to.
477
478       store
479             my $store  = $wiki->store;
480             my $dbname = eval { $wiki->store->dbname; }
481               or warn "Not a DB backend";
482
483           Returns the storage backend object.
484
485       search_obj
486             my $search_obj = $wiki->search_obj;
487
488           Returns the search backend object.
489
490       formatter
491             my $formatter = $wiki->formatter;
492
493           Returns the formatter backend object.
494

SEE ALSO

496       For a very quick Wiki startup without any of that icky programming
497       stuff, see Tom Insam's Wiki::Toolkit::Kwiki, an instant wiki based on
498       Wiki::Toolkit.
499
500       Or for the specialised application of a wiki about a city, see the
501       OpenGuides distribution.
502
503       Wiki::Toolkit allows you to use different formatting modules.
504       Text::WikiFormat might be useful for anyone wanting to write a custom
505       formatter. Existing formatters include:
506
507       ·   Wiki::Toolkit::Formatter::Default (in this distro)
508
509       ·   Wiki::Toolkit::Formatter::Pod
510
511       ·   Wiki::Toolkit::Formatter::UseMod
512
513       There's currently a choice of three storage backends - all database-
514       backed.
515
516       ·   Wiki::Toolkit::Store::MySQL (in this distro)
517
518       ·   Wiki::Toolkit::Store::Pg (in this distro)
519
520       ·   Wiki::Toolkit::Store::SQLite (in this distro)
521
522       ·   Wiki::Toolkit::Store::Database (parent class for the above - in
523           this distro)
524
525       A search backend is optional:
526
527       ·   Wiki::Toolkit::Search::DBIxFTS (in this distro, uses
528           DBIx::FullTextSearch)
529
530       ·   Wiki::Toolkit::Search::SII (in this distro, uses
531           Search::InvertedIndex)
532
533       Standalone plugins can also be written - currently they should only
534       read from the backend storage, but write access guidelines are coming
535       soon. Plugins written so far and available from CPAN:
536
537       ·   Wiki::Toolkit::Plugin::GeoCache
538
539       ·   Wiki::Toolkit::Plugin::Categoriser
540
541       ·   Wiki::Toolkit::Plugin::Locator::UK
542
543       ·   Wiki::Toolkit::Plugin::RSS::ModWiki
544
545       If writing a plugin you might want an easy way to run tests for it on
546       all possible backends:
547
548       ·   Wiki::Toolkit::TestConfig::Utilities (in this distro)
549
550       Other ways to implement Wikis in Perl include:
551
552       ·   CGI::Kwiki (an instant wiki)
553
554       ·   CGI::pWiki
555
556       ·   AxKit::XSP::Wiki
557
558       ·   Apache::MiniWiki
559
560       ·   UseModWiki <http://usemod.com>
561
562       ·   Chiq Chaq <http://chiqchaq.sourceforge.net/>
563

AUTHOR

565       Kake Pugh (kake@earth.li) and the Wiki::Toolkit team (including Nick
566       Burch and Dominic Hargreaves)
567

SUPPORT

569       Questions should go to cgi-wiki-dev@earth.li.
570
572            Copyright (C) 2002-2004 Kake Pugh.  All Rights Reserved.
573            Copyright (C) 2006-2013 the Wiki::Toolkit team. All Rights Reserved.
574
575       This module is free software; you can redistribute it and/or modify it
576       under the same terms as Perl itself.
577

FEEDBACK

579       The developer web site and bug tracker is at
580         http://www.wiki-toolkit.org/ - please file bugs there as appropriate.
581
582       You could also subscribe to the dev list at
583         http://www.earth.li/cgi-bin/mailman/listinfo/cgi-wiki-dev
584

BUGS

586       Versions between 0.75 and 0.79 inclusive contain a bug which prevents
587       Recent Changes routines from working correctly if minor changes are
588       excluded <http://www.wiki-toolkit.org/ticket/41>. You may wish to avoid
589       upgrading to this version until it is fixed if this is important to
590       you; the fix is however not trivial so noone has been able to step up
591       yet.
592
593       Other minor bugs are documented at <http://www.wiki-toolkit.org/report>
594

CREDITS

596       Various London.pm types helped out with code review, encouragement,
597       JFDI, style advice, code snippets, module recommendations, and so on;
598       far too many to name individually, but particularly Richard Clamp, Tony
599       Fisher, Mark Fowler, and Chris Ball.
600
601       blair christensen sent patches and gave me some good ideas. chromatic
602       continues to patiently apply my patches to Text::WikiFormat and help me
603       get it working in just the way I need. Paul Makepeace helped me add
604       support for connecting to non-local databases. Shevek has been prodding
605       me a lot lately. The OpenGuides team keep me well-supplied with
606       encouragement and bug reports.
607
608       Nick Burch has been leading the way with development leading up to the
609       release under the Wiki::Toolkit name.
610

GRATUITOUS PLUG

612       I'm only obsessed with Wikis because of the Open Guide to London --
613       <http://openguides.org/london/>
614
615
616
617perl v5.32.0                      2020-07-28                  Wiki::Toolkit(3)
Impressum