Rather more work than can be completed in one evening -- needs a
[cocanwiki.git] / scripts / links.ml
1 (* COCANWIKI - a wiki written in Objective CAML.
2  * Written by Richard W.M. Jones <rich@merjis.com>.
3  * Copyright (C) 2004 Merjis Ltd.
4  * $Id: links.ml,v 1.3 2006/03/27 18:09:46 rich Exp $
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; see the file COPYING.  If not, write to
18  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  *)
21
22 open Apache
23 open Registry
24 open Cgi
25 open Printf
26
27 open Cocanwiki
28 open Cocanwiki_template
29 open Cocanwiki_links
30
31 (* This script produces the links database for the whole site (if
32  * called without the 'page' parameter), or else just for a particular
33  * page.  If called with 'page' and 'type' parameters together, then it
34  * can show inbound or outbound links only.  The format in all cases is a
35  * simple machine-parsable text file.
36  *)
37 let run r (q : cgi) dbh hostid _ _ =
38   let template = get_template dbh hostid "links.txt" in
39
40   if q#param_exists "page" then (
41     let page = q#param "page" in
42     let page = if page = "" then "index" else page in
43
44     if q#param_exists "type" then (
45       let type_ = q#param "type" in
46
47       if type_ = "inbound" then (
48         (* This is "what links here".  We're interested in indirect
49          * links too, so use Cocanwiki_links.what_links_here function.
50          *)
51         let links = what_links_here dbh hostid page in
52         let links = List.map fst links in
53
54         q#header ~content_type:"text/plain" ();
55
56         List.iter (fun url -> ignore (print_endline r url)) links
57
58       ) else if type_ = "outbound" then (
59         (* Display a list of links outbound from this page. *)
60         let sth =
61           dbh#prepare_cached "select to_url from links
62                                where hostid = ? and from_url = ?" in
63
64         sth#execute [Some hostid; Some page];
65
66         q#header ~content_type:"text/plain" ();
67
68         sth#iter (function [Some url] -> ignore (print_endline r url)
69                     | _ -> assert false)
70
71       ) else
72         failwith "'type' parameter should be 'inbound' or 'outbound'"
73
74     ) else (
75       (* Just return the single-row "links database" relating to this
76        * page.
77        *)
78       let sth = dbh#prepare_cached "select to_url from links
79                                      where hostid = ? and from_url = ?" in
80       sth#execute [Some hostid; Some page];
81
82       let table =
83         sth#map (function [Some to_url] ->
84                    [ "to", Template.VarString to_url ]
85                    | _ -> assert false) in
86       let table =
87         [ [ "from", Template.VarString page;
88             "to", Template.VarTable table ] ] in
89       template#table "links" table;
90
91       q#template ~content_type:"text/plain" template
92     )
93   ) else (
94     (* Links database for whole site in the simple format required by
95      * the TouchGraph application.  We don't know anything about external
96      * links, so we don't include them.  However we do include links to
97      * non-existant internal pages.
98      *)
99     let h = Hashtbl.create 1024 in
100     let add_link from_url to_url =
101       let xs = try Hashtbl.find h from_url with Not_found -> [] in
102       let xs = to_url :: xs in
103       Hashtbl.replace h from_url xs
104     in
105
106     let sth = dbh#prepare_cached "select from_url, to_url from links
107                                    where hostid = ?" in
108     sth#execute [Some hostid];
109
110     sth#iter (function [Some from_url; Some to_url] ->
111                 add_link from_url to_url
112                 | _ -> assert false);
113
114     (* Don't forget redirects!  They're kinda like links ... *)
115     let sth = dbh#prepare_cached "select url, redirect from pages
116                                    where hostid = ? and url is not null
117                                      and redirect is not null" in
118     sth#execute [Some hostid];
119
120     sth#iter (function [Some url; Some redirect] ->
121                 add_link url redirect
122                 | _ -> assert false);
123
124     let keys h = Hashtbl.fold (fun key _ xs -> key :: xs) h [] in
125
126     let table =
127       List.map
128         (fun from ->
129            let xs = Hashtbl.find h from in
130            let table =
131              List.map (fun to_ -> [ "to", Template.VarString to_ ]) xs in
132            [ "from", Template.VarString from;
133              "to", Template.VarTable table ]
134         ) (keys h) in
135     template#table "links" table;
136
137     q#template ~content_type:"text/plain" template
138   )
139
140 let () =
141   register_script ~restrict:[CanView] run