Strict limit on the number of links in the 'what links here' section.
[cocanwiki.git] / scripts / page.ml
index 29dd3bb..bfd7bd6 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.
- * $Id: page.ml,v 1.27 2004/10/10 14:44:50 rich Exp $
+ * $Id: page.ml,v 1.32 2004/10/10 19:19:58 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
@@ -25,12 +25,14 @@ open Cgi
 open Printf
 
 open ExtString
+open ExtList
 
 open Cocanwiki
 open Cocanwiki_template
 open Cocanwiki_ok
 open Cocanwiki_date
 open Cocanwiki_server_settings
+open Cocanwiki_links
 
 type fp_status = FPOK of int * string * string * Dbi.datetime * bool
               | FPRedirect of string
@@ -63,14 +65,15 @@ let run r (q : cgi) (dbh : Dbi.connection) hostid
   (* Host-specific fields. *)
   let sth = dbh#prepare_cached "select css is not null,
                                        feedback_email is not null,
-                                       mailing_list, search_box
+                                       mailing_list, search_box, navigation
                                   from hosts where id = ?" in
   sth#execute [`Int hostid];
-  let has_host_css, has_feedback_email, mailing_list, search_box =
+  let has_host_css, has_feedback_email, mailing_list, search_box, navigation =
     match sth#fetch1 () with
       | [ `Bool has_host_css; `Bool has_feedback_email; `Bool mailing_list;
-         `Bool search_box ] ->
-         has_host_css, has_feedback_email, mailing_list, search_box
+         `Bool search_box; `Bool navigation ] ->
+         has_host_css, has_feedback_email, mailing_list, search_box,
+         navigation
       | _ -> assert false in
 
   (* Can the user edit?  Manage users?  etc. *)
@@ -196,6 +199,7 @@ let run r (q : cgi) (dbh : Dbi.connection) hostid
     t#conditional "has_feedback_email" has_feedback_email;
     t#conditional "mailing_list" mailing_list;
     t#conditional "search_box" search_box;
+    t#conditional "navigation" navigation;
 
     t#conditional "can_edit" can_edit;
     t#conditional "can_manage_users" can_manage_users;
@@ -275,6 +279,75 @@ let run r (q : cgi) (dbh : Dbi.connection) hostid
           t#conditional "user_logged_in" true;
           t#set "username" username);
 
+    (* If logged in, we want to update the recently_visited table. *)
+    if pageid <> None then (
+      match user with
+       | User (userid, _, _) ->
+           let sth = dbh#prepare_cached "delete from recently_visited
+                                           where hostid = ? and userid = ?
+                                             and url = ?" in
+           sth#execute [`Int hostid; `Int userid; `String page'];
+           let sth = dbh#prepare_cached
+                       "insert into recently_visited (hostid, userid, url)
+                         values (?, ?, ?)" in
+           sth#execute [`Int hostid; `Int userid; `String page'];
+           dbh#commit ()
+       | _ -> ()
+    );
+
+    (* Navigation links. *)
+    if navigation then (
+      let max_links = 18 in            (* Show no more links than this. *)
+
+      (* What links here. *)
+      let wlh = what_links_here dbh hostid page' in
+      let wlh = List.take max_links wlh in
+      let wlh_urls = List.map fst wlh in (* Just the URLs ... *)
+
+      let rv =
+       match user with
+         | User (userid, _, _) ->
+             (* Recently visited URLs, but don't repeat any from the 'what
+              * links here' section, and don't link to self.
+              *)
+             let not_urls = page' :: wlh_urls in
+             let limit = max_links - List.length wlh_urls in
+             let qs = Dbi.placeholders (List.length not_urls) in
+             let sth =
+               dbh#prepare_cached
+                 ("select rv.url, p.title, rv.visit_time
+                      from recently_visited rv, pages p
+                     where rv.hostid = ? and rv.userid = ?
+                       and rv.url not in " ^ qs ^ "
+                       and rv.hostid = p.hostid and rv.url = p.url
+                     order by 3 desc
+                     limit ?") in
+             let args = List.map (fun s -> `String s) not_urls in
+             sth#execute
+               ([`Int hostid; `Int userid] @ args @ [`Int limit]);
+             sth#map
+               (function [`String url; `String title; _] ->
+                  url, title
+                  | _ -> assert false)
+         | _ -> [] in
+
+      (* Links to page. *)
+      let f (page, title) = [ "page", Template.VarString page;
+                             "title", Template.VarString title ] in
+      let table = List.map f wlh in
+      t#table "what_links_here" table;
+      t#conditional "has_what_links_here" (wlh <> []);
+
+      let table = List.map f rv in
+      t#table "recently_visited" table;
+      t#conditional "has_recently_visited" (rv <> []);
+
+      (* If both lists are empty (ie. an empty navigation box would
+       * appear), then disable navigation altogether.
+       *)
+      if wlh = [] && rv = [] then t#conditional "navigation" false
+    );
+
     (* If we are coming from a search engine then we want to highlight
      * search terms throughout the whole page ...
      *)