+(* COCANWIKI - a wiki written in Objective CAML.
+ * Written by Richard W.M. Jones <rich@merjis.com>.
+ * Copyright (C) 2004 Merjis Ltd.
+ * $Id: links.ml,v 1.1 2004/10/27 21:14:05 rich Exp $
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *)
+
+open Apache
+open Registry
+open Cgi
+open Printf
+
+open Cocanwiki
+open Cocanwiki_template
+open Cocanwiki_links
+
+(* This script produces the links database for the whole site (if
+ * called without the 'page' parameter), or else just for a particular
+ * page. If called with 'page' and 'type' parameters together, then it
+ * can show inbound or outbound links only. The format in all cases is a
+ * simple machine-parsable text file.
+ *)
+let run r (q : cgi) (dbh : Dbi.connection) hostid _ _ =
+ let template = get_template dbh hostid "links.txt" in
+
+ if q#param_exists "page" then (
+ let page = q#param "page" in
+ let page = if page = "" then "index" else page in
+
+ if q#param_exists "type" then (
+ let type_ = q#param "type" in
+
+ if type_ = "inbound" then (
+ (* This is "what links here". We're interested in indirect
+ * links too, so use Cocanwiki_links.what_links_here function.
+ *)
+ let links = what_links_here dbh hostid page in
+ let links = List.map fst links in
+
+ q#header ~content_type:"text/plain" ();
+
+ List.iter (fun url -> ignore (print_endline r url)) links
+
+ ) else if type_ = "outbound" then (
+ (* Display a list of links outbound from this page. *)
+ let sth =
+ dbh#prepare_cached "select to_url from links
+ where hostid = ? and from_url = ?" in
+
+ sth#execute [`Int hostid; `String page];
+
+ q#header ~content_type:"text/plain" ();
+
+ sth#iter (function [`String url] -> ignore (print_endline r url)
+ | _ -> assert false)
+
+ ) else
+ failwith "'type' parameter should be 'inbound' or 'outbound'"
+
+ ) else (
+ (* Just return the single-row "links database" relating to this
+ * page.
+ *)
+ let sth = dbh#prepare_cached "select to_url from links
+ where hostid = ? and from_url = ?" in
+ sth#execute [`Int hostid; `String page];
+
+ let table =
+ sth#map (function [`String to_url] ->
+ [ "to", Template.VarString to_url ]
+ | _ -> assert false) in
+ let table =
+ [ [ "from", Template.VarString page;
+ "to", Template.VarTable table ] ] in
+ template#table "links" table;
+
+ q#template ~content_type:"text/plain" template
+ )
+ ) else (
+ (* Links database for whole site in the simple format required by
+ * the TouchGraph application. We don't know anything about external
+ * links, so we don't include them. However we do include links to
+ * non-existant internal pages.
+ *)
+ let h = Hashtbl.create 1024 in
+ let add_link from_url to_url =
+ let xs = try Hashtbl.find h from_url with Not_found -> [] in
+ let xs = to_url :: xs in
+ Hashtbl.replace h from_url xs
+ in
+
+ let sth = dbh#prepare_cached "select from_url, to_url from links
+ where hostid = ?" in
+ sth#execute [`Int hostid];
+
+ sth#iter (function [`String from_url; `String to_url] ->
+ add_link from_url to_url
+ | _ -> assert false);
+
+ (* Don't forget redirects! They're kinda like links ... *)
+ let sth = dbh#prepare_cached "select url, redirect from pages
+ where hostid = ? and url is not null
+ and redirect is not null" in
+ sth#execute [`Int hostid];
+
+ sth#iter (function [`String url; `String redirect] ->
+ add_link url redirect
+ | _ -> assert false);
+
+ let keys h = Hashtbl.fold (fun key _ xs -> key :: xs) h [] in
+
+ let table =
+ List.map
+ (fun from ->
+ let xs = Hashtbl.find h from in
+ let table =
+ List.map (fun to_ -> [ "to", Template.VarString to_ ]) xs in
+ [ "from", Template.VarString from;
+ "to", Template.VarTable table ]
+ ) (keys h) in
+ template#table "links" table;
+
+ q#template ~content_type:"text/plain" template
+ )
+
+let () =
+ register_script run