Changes done on the Mac.
[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.4 2006/03/28 13:20:00 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 rows =
61           PGSQL(dbh)
62             "select to_url from links
63               where hostid = $hostid and from_url = $page" in
64
65         q#header ~content_type:"text/plain" ();
66
67         List.iter (fun url -> ignore (print_endline r url))
68
69       ) else
70         failwith "'type' parameter should be 'inbound' or 'outbound'"
71
72     ) else (
73       (* Just return the single-row "links database" relating to this
74        * page.
75        *)
76       let rows = PGSQL(dbh)
77         "select to_url from links
78           where hostid = $hostid and from_url = $page" in
79
80       let table =
81         List.map (fun to_url ->
82                    [ "to", Template.VarString to_url ]) rows in
83       let table =
84         [ [ "from", Template.VarString page;
85             "to", Template.VarTable table ] ] in
86       template#table "links" table;
87
88       q#template ~content_type:"text/plain" template
89     )
90   ) else (
91     (* Links database for whole site in the simple format required by
92      * the TouchGraph application.  We don't know anything about external
93      * links, so we don't include them.  However we do include links to
94      * non-existant internal pages.
95      *)
96     let h = Hashtbl.create 1024 in
97     let add_link from_url to_url =
98       let xs = try Hashtbl.find h from_url with Not_found -> [] in
99       let xs = to_url :: xs in
100       Hashtbl.replace h from_url xs
101     in
102
103     let rows = PGSQL(dbh) "select from_url, to_url from links
104                             where hostid = $hostid" in
105
106     sth#iter (fun (from_url, to_url) ->
107                 add_link from_url to_url) rows;
108
109     (* Don't forget redirects!  They're kinda like links ... *)
110     let rows = PGSQL(dbh) "select url, redirect from pages
111                             where hostid = $hostid and url is not null
112                               and redirect is not null" in
113
114     sth#iter (function
115               | (url, Some redirect) -> add_link url redirect
116               | (_, None) -> ()
117              ) rows;
118
119     let keys h = Hashtbl.fold (fun key _ xs -> key :: xs) h [] in
120
121     let table =
122       List.map
123         (fun from ->
124            let xs = Hashtbl.find h from in
125            let table =
126              List.map (fun to_ -> [ "to", Template.VarString to_ ]) xs in
127            [ "from", Template.VarString from;
128              "to", Template.VarTable table ]
129         ) (keys h) in
130     template#table "links" table;
131
132     q#template ~content_type:"text/plain" template
133   )
134
135 let () =
136   register_script ~restrict:[CanView] run