Factored out the 'what links here' code into cocanwiki_links library.
authorrich <rich>
Sun, 10 Oct 2004 14:44:50 +0000 (14:44 +0000)
committerrich <rich>
Sun, 10 Oct 2004 14:44:50 +0000 (14:44 +0000)
Fixed it so that it can discover links mediated by redirects.

max_redirect moved from page.ml because it's used in other places.

scripts/cocanwiki.ml
scripts/cocanwiki_links.ml
scripts/cocanwiki_links.mli
scripts/page.ml
scripts/what_links_here.ml

index 5664582..8cca6fb 100644 (file)
@@ -1,7 +1,7 @@
 (* COCANWIKI - a wiki written in Objective CAML.
  * Written by Richard W.M. Jones <rich@merjis.com>.
  * Copyright (C) 2004 Merjis Ltd.
 (* COCANWIKI - a wiki written in Objective CAML.
  * Written by Richard W.M. Jones <rich@merjis.com>.
  * Copyright (C) 2004 Merjis Ltd.
- * $Id: cocanwiki.ml,v 1.15 2004/10/07 16:54:24 rich Exp $
+ * $Id: cocanwiki.ml,v 1.16 2004/10/10 14:44:50 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
  *
  * 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
@@ -222,3 +222,6 @@ let linkname_of_sectionname str =
 (* List of extensions currently registered. *)
 type extension_t = Dbi.connection -> int -> string -> string
 let extensions = ref ([] : (string * extension_t) list)
 (* List of extensions currently registered. *)
 type extension_t = Dbi.connection -> int -> string -> string
 let extensions = ref ([] : (string * extension_t) list)
+
+(* Maximum degree of redirection. *)
+let max_redirect = 4
index 101ca64..99ee987 100644 (file)
@@ -1,7 +1,7 @@
 (* COCANWIKI - a wiki written in Objective CAML.
  * Written by Richard W.M. Jones <rich@merjis.com>.
  * Copyright (C) 2004 Merjis Ltd.
 (* COCANWIKI - a wiki written in Objective CAML.
  * Written by Richard W.M. Jones <rich@merjis.com>.
  * Copyright (C) 2004 Merjis Ltd.
- * $Id: cocanwiki_links.ml,v 1.3 2004/10/07 12:22:11 rich Exp $
+ * $Id: cocanwiki_links.ml,v 1.4 2004/10/10 14:44:50 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
  *
  * 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
@@ -22,6 +22,8 @@
 open ExtString
 open ExtList
 
 open ExtString
 open ExtList
 
+open Cocanwiki
+
 let split_tags_re = Pcre.regexp ~flags:[`DOTALL] "<.*?>|[^<]+"
 let internal_re = Pcre.regexp "class=\"internal\""
 let newpage_re = Pcre.regexp "class=\"newpage\""
 let split_tags_re = Pcre.regexp ~flags:[`DOTALL] "<.*?>|[^<]+"
 let internal_re = Pcre.regexp "class=\"internal\""
 let newpage_re = Pcre.regexp "class=\"newpage\""
@@ -122,3 +124,50 @@ let update_links_for_page dbh hostid page =
        let links = get_links_from_section dbh hostid content in
        List.iter (insert_link dbh hostid page) links
        | _ -> assert false)
        let links = get_links_from_section dbh hostid content in
        List.iter (insert_link dbh hostid page) links
        | _ -> assert false)
+
+(* Because of redirects, getting the list of pages which link to this
+ * page isn't a matter of just doing 'select from_url from links ...'.
+ * We also look at pages which redirect to this URL (for redirections
+ * of degrees 1 through 4 = max_redirect).
+ *)
+let what_links_here (dbh : Dbi.connection) hostid page =
+  (* Build up the complete list of URLs which redirect to the target
+   * page, within max_redirect redirections.  This is sort of like
+   * Prim's algorithm.
+   *)
+  let urls = ref [page] in
+  let found = ref true in
+  let i = ref 1 in
+  while !found && !i <= max_redirect do
+    let qs = Dbi.placeholders (List.length !urls) in
+    let sql =
+      "select url from pages
+        where hostid = ?
+          and url is not null and redirect is not null
+          and url not in " ^ qs ^ " and redirect in " ^ qs in
+    let sth = dbh#prepare_cached sql in
+    let args = List.map (fun s -> `String s) !urls in
+    sth#execute (`Int hostid :: (args @ args));
+    let new_urls = sth#map (function [`String s] -> s | _ -> assert false) in
+    urls := !urls @ new_urls;
+    found := new_urls <> [];
+    incr i
+  done;
+
+  let urls = !urls in
+
+  (* Now find any pages which link to one of these target pages.  For
+   * convenience we also select out the titles.
+   *)
+  let qs = Dbi.placeholders (List.length urls) in
+  let sth =
+    dbh#prepare_cached
+      ("select li.from_url, p.title
+          from links li, pages p
+         where li.hostid = ? and li.to_url in " ^ qs ^ "
+           and li.hostid = p.hostid and li.from_url = p.url") in
+  sth#execute (`Int hostid :: (List.map (fun s -> `String s) urls));
+
+  sth#map (function
+            | [`String url; `String title] -> url, title
+            | _ -> assert false)
index b55e26c..de2b615 100644 (file)
@@ -1,7 +1,7 @@
 (* COCANWIKI - a wiki written in Objective CAML.
  * Written by Richard W.M. Jones <rich@merjis.com>.
  * Copyright (C) 2004 Merjis Ltd.
 (* COCANWIKI - a wiki written in Objective CAML.
  * Written by Richard W.M. Jones <rich@merjis.com>.
  * Copyright (C) 2004 Merjis Ltd.
- * $Id: cocanwiki_links.mli,v 1.2 2004/09/28 11:28:39 rich Exp $
+ * $Id: cocanwiki_links.mli,v 1.3 2004/10/10 14:44:50 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
  *
  * 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
@@ -22,3 +22,5 @@
 val get_links_from_section : Dbi.connection -> int -> string -> string list
 val update_links_for_page : Dbi.connection -> int -> string -> unit
 val insert_link : Dbi.connection -> int -> string -> string -> unit
 val get_links_from_section : Dbi.connection -> int -> string -> string list
 val update_links_for_page : Dbi.connection -> int -> string -> unit
 val insert_link : Dbi.connection -> int -> string -> string -> unit
+
+val what_links_here : Dbi.connection -> int -> string -> (string * string) list
index 7e2f02d..29dd3bb 100644 (file)
@@ -1,7 +1,7 @@
 (* COCANWIKI - a wiki written in Objective CAML.
  * Written by Richard W.M. Jones <rich@merjis.com>.
  * Copyright (C) 2004 Merjis Ltd.
 (* COCANWIKI - a wiki written in Objective CAML.
  * Written by Richard W.M. Jones <rich@merjis.com>.
  * Copyright (C) 2004 Merjis Ltd.
- * $Id: page.ml,v 1.26 2004/10/07 16:54:24 rich Exp $
+ * $Id: page.ml,v 1.27 2004/10/10 14:44:50 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
  *
  * 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
@@ -32,9 +32,6 @@ open Cocanwiki_ok
 open Cocanwiki_date
 open Cocanwiki_server_settings
 
 open Cocanwiki_date
 open Cocanwiki_server_settings
 
-(* Maximum level of redirection. *)
-let max_redirect = 4
-
 type fp_status = FPOK of int * string * string * Dbi.datetime * bool
               | FPRedirect of string
               | FPNotFound
 type fp_status = FPOK of int * string * string * Dbi.datetime * bool
               | FPRedirect of string
               | FPNotFound
index f05994c..80a7c4f 100644 (file)
@@ -1,7 +1,7 @@
 (* COCANWIKI - a wiki written in Objective CAML.
  * Written by Richard W.M. Jones <rich@merjis.com>.
  * Copyright (C) 2004 Merjis Ltd.
 (* COCANWIKI - a wiki written in Objective CAML.
  * Written by Richard W.M. Jones <rich@merjis.com>.
  * Copyright (C) 2004 Merjis Ltd.
- * $Id: what_links_here.ml,v 1.3 2004/10/04 15:19:56 rich Exp $
+ * $Id: what_links_here.ml,v 1.4 2004/10/10 14:44:50 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
  *
  * 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
@@ -26,6 +26,7 @@ open Printf
 
 open Cocanwiki
 open Cocanwiki_template
 
 open Cocanwiki
 open Cocanwiki_template
+open Cocanwiki_links
 
 let run r (q : cgi) (dbh : Dbi.connection) hostid _ _ =
   let template = get_template dbh hostid "what_links_here.html" in
 
 let run r (q : cgi) (dbh : Dbi.connection) hostid _ _ =
   let template = get_template dbh hostid "what_links_here.html" in
@@ -40,18 +41,11 @@ let run r (q : cgi) (dbh : Dbi.connection) hostid _ _ =
   let title = sth#fetch1string () in
   template#set "title" title;
 
   let title = sth#fetch1string () in
   template#set "title" title;
 
-  let sth =
-    dbh#prepare_cached "select l.from_url, p.title from links l, pages p
-                         where l.hostid = ? and l.to_url = ?
-                           and l.hostid = p.hostid and l.from_url = p.url" in
-  sth#execute [`Int hostid; `String page];
-
+  let pages = what_links_here dbh hostid page in
   let table =
   let table =
-    sth#map
-      (function [`String page; `String title] ->
-        [ "page", Template.VarString page;
-          "title", Template.VarString title ]
-        | _ -> assert false) in
+    List.map (fun (page, title) ->
+               [ "page", Template.VarString page;
+                 "title", Template.VarString title ]) pages in
 
   template#table "pages" table;
   template#conditional "pages_empty" (table = []);
 
   template#table "pages" table;
   template#conditional "pages_empty" (table = []);