Wikka : PageAdminAction

HomePage :: Categories :: Index :: Changes :: Comments :: Documentation :: Blog :: Login/Register

Page Administration Action

Last edited by DarTar:
link to docs


This is the development page for the Page Administration action. The Page Administration module has been committed to the 1.1.6.4 branch and will be available with the 1.1.6.4 release. Documentation http://docs.wikkawiki.org/PageAdministration

This action, inspired by the UserAdmin action, is meant to allow Wikka Administrators to manage pages and perform several maintenance operations.
It displays the standard PageIndex to non-admins.

See also:
Table of Contents:
 



Sample output

Page Administration


Filter view:

Records (912): 1-20 | 21-40
(Sorted by:time, desc)
Page Name Owner Last Author Last Edit Hits Revisions Comments Backlinks Referrers Actions
UserAdmin DarTar DarTar 2005-08-01 14:48:30 0 57 7 19 54 edit :: delete :: clone :: acl :: info
LastUsers DarTar DarTar 2005-08-01 14:44:39 0 1 0 1 0 edit :: delete :: clone :: acl :: info
TableStyling DarTar DarTar 2005-08-01 14:37:32 0 2 0 1 0 edit :: delete :: clone :: acl :: info
UserMap NilsLindenberg DennyShimkoski 2005-08-01 13:28:40 0 28 0 5 121 edit :: delete :: clone :: acl :: info
DennyShimkos… DennyShimkoski DennyShimkoski 2005-08-01 13:21:31 0 11 2 7 0 edit :: delete :: clone :: acl :: info
TestSkin (Public) DarTar 2005-08-01 13:04:34 0 34 21 31 257 edit :: delete :: clone :: acl :: info
HypeXR HypeXR HypeXR 2005-08-01 09:09:40 0 2 0 0 0 edit :: delete :: clone :: acl :: info
CustomCSS DennyShimkoski DennyShimkoski 2005-08-01 05:39:11 0 3 0 1 0 edit :: delete :: clone :: acl :: info
OnPageLoadWi… DennyShimkoski DennyShimkoski 2005-08-01 05:32:33 0 5 0 2 0 edit :: delete :: clone :: acl :: info
UncamelActio… DennyShimkoski DennyShimkoski 2005-08-01 05:30:38 0 4 0 2 0 edit :: delete :: clone :: acl :: info
ChristianBar… ChristianBarthelemy DennyShimkoski 2005-07-31 14:39:37 0 39 8 19 49 edit :: delete :: clone :: acl :: info
WikkaSites (Public) DarTar 2005-07-31 09:30:11 0 419 31 17 470 edit :: delete :: clone :: acl :: info
HomePage (Public) DarTar 2005-07-31 09:13:49 0 183 96 49 33437 edit :: delete :: clone :: acl :: info
InfoHandler DarTar DarTar 2005-07-31 08:28:43 0 20 0 2 0 edit :: delete :: clone :: acl :: info
DennysCalend… DennyShimkoski DennyShimkoski 2005-07-31 06:52:55 0 5 0 2 0 edit :: delete :: clone :: acl :: info
JwCalendarWi… ChristianBarthelemy DennyShimkoski 2005-07-31 06:43:47 0 8 6 3 52 edit :: delete :: clone :: acl :: info
SandBox (Public) PaulWittenbraker 2005-07-31 03:37:29 0 1116 13 34 108 edit :: delete :: clone :: acl :: info
TonExtraWiki PaulWittenbraker PaulWittenbraker 2005-07-31 03:10:51 0 1 0 1 0 edit :: delete :: clone :: acl :: info
CodeContribu… (Public) DennyShimkoski 2005-07-31 02:23:42 0 124 4 28 144 edit :: delete :: clone :: acl :: info
DennysAttach… DennyShimkoski DennyShimkoski 2005-07-31 01:24:04 0 4 0 2 0 edit :: delete :: clone :: acl :: info
Mass-action[Check all | Uncheck all]


Current version


Latest available version: 0.4.

Features:
Bugfixes and modifications:

To do


The code


Save the code below as actions/pageadmin.php and use it as {{pageadmin}}.

Note: The code has been adapted to take advantage of the getCount() and FormatUser() methods, which are required for the action to work.

  1. <?php
  2.  
  3. /**
  4. * Display a module for page management.
  5. *
  6. * This action allows admins to display information and perform operations
  7. * on wiki pages. Pages can be sorted, searched, paged, filtered. Page-related
  8. * statistics are given, displaying the number of comments, revisions, backlinks
  9. * and referrers. Several handlers allow admins to perform specific operation on
  10. * single pages. If the current user is not an administrator, the pageindex action
  11. * is displayed instead.
  12. *
  13. * @package        Actions
  14. * @name        PageAdmin
  15. *
  16. * @author        {@link http://wikka.jsnx.com/DarTar Dario Taraborelli}
  17. * @author        {@link http://wikka.jsnx.com/JavaWoman JavaWoman} (using getCount(); minor tweaks)
  18. * @version        0.4
  19. * @since        Wikka 1.1.X.X
  20. *
  21. * @input        integer $colcolor  optional: enables color for statistics columns
  22. *                1: enables colored columns;
  23. *                0: disables colored columns;
  24. *                default: 1;
  25. * @input        integer $rowcolor  optional: enables alternate row colors
  26. *                1: enables colored rows;
  27. *                0: disables colored rows;
  28. *                default: 1;
  29. *
  30. * @output        A list of pages available on the current server.
  31. *
  32. * @todo   
  33. *            - mass-operations;
  34. *            - handlers: rename handler;
  35. *            - statistics: page hits;
  36. *            - full-text page search;
  37. *            - integrate with other admin modules.
  38. */
  39.  
  40. //utilities
  41.  
  42. /**
  43. * Build an array of numbers consisting of 'ranges' with increasing step size in each 'range'.
  44. *
  45. * A list of numbers like this is useful for instance for a dropdown to choose
  46. * a period expressed in number of days: a difference between 2 and 5 days may
  47. * be significant while that between 92 and 95 may not be.
  48. *
  49. * @author        {@link http://wikka.jsnx.com/JavaWoman JavaWoman}
  50. * @copyright    Copyright (c) 2005, Marjolein Katsma
  51. * @license        http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
  52. * @version        1.0
  53. *
  54. * @param    mixed    $limits    required: single integer or array of integers;
  55. *                    defines the upper limits of the ranges as well as the next step size
  56. * @param    int        $max    required: upper limit for the whole list
  57. *                    (will be included if smaller than the largest limit)
  58. * @param    int        $firstinc optional: increment for the first range; default 1
  59. * @return    array    resulting list of numbers
  60. */
  61. function optionRanges($limits, $max, $firstinc = 1)
  62. {
  63.     // initializations
  64.     if (is_int($limits)) $limits = array($limits);
  65.     if ($firstinc < 1) $firstinc = 1;
  66.     $opts = array();
  67.     $inc = $firstinc;
  68.  
  69.     // first element is the first increment
  70.     $opts[] = $inc;
  71.     // each $limit is the upper limit of a 'range'
  72.     foreach ($limits as $limit)
  73.     {
  74.         for ($i = $inc + $inc; $i <= $limit && $i < $max; $i += $inc)
  75.         {
  76.             $opts[] = $i;
  77.         }
  78.         // we quit at $max, even if there are more $limit elements
  79.         if ($limit >= $max)
  80.         {
  81.             // add $max to the list; then break out of the loop
  82.             $opts[] = $max;
  83.             break;
  84.         }
  85.         // when $limit is reached, it becomes the new start and increment for the next 'range'
  86.         $inc = $limit;
  87.     }
  88.  
  89.     return $opts;
  90. }
  91.  
  92. // restrict access to admins
  93. if ($this->IsAdmin($this->GetUser())) {
  94.  
  95.     // -------------------------------------
  96.     // set default values as constants
  97.     define('DEFAULT_RECORDS_LIMIT', '20'); # number of records per page
  98.     define('DEFAULT_MIN_RECORDS_DISPLAY', '5'); # min number of records
  99.     define('DEFAULT_RECORDS_RANGE',serialize(array('10','50','100','500','1000'))); #range array for records pager
  100.     define('DEFAULT_SORT_FIELD', 'time'); # sort field
  101.     define('DEFAULT_SORT_ORDER', 'desc'); # sort order, ascendant or descendant
  102.     define('DEFAULT_START', '0'); # start record
  103.     define('DEFAULT_SEARCH', ''); # keyword to restrict page search
  104.     define('DEFAULT_TAG_LENGTH', '12'); # max. length of displayed pagename
  105.     define('DEFAULT_URL_LENGTH', '15'); # max. length of displayed user host
  106.     define('DEFAULT_TERMINATOR', '…'); # standard symbol replacing truncated text (ellipsis) JW 2005-07-19
  107.     define('ALTERNATE_ROW_COLOR', '1'); # switch alternate row color
  108.     define('STAT_COLUMN_COLOR', '1'); # switch color for statistics columns
  109.    
  110.     // -------------------------------------
  111.     // User-interface: icons
  112.    
  113.     define('HITS_ICON', 'images/icons/16x16/stock_about.png');
  114.     define('REVISIONS_ICON', 'images/icons/16x16/stock_book_open.png');
  115.     define('COMMENTS_ICON', 'images/icons/16x16/stock_help-agent.png');
  116.     define('BACKLINKS_ICON', 'images/icons/16x16/stock_link.png');
  117.     define('REFERRERS_ICON', 'images/icons/16x16/stock_internet.png');
  118.    
  119.    
  120.     // -------------------------------------
  121.     // User-interface: strings
  122.    
  123.     define('PAGE_TITLE','Page Administration');
  124.     define('FORM_LEGEND','Filter view:');
  125.     define('FORM_SEARCH_STRING_LABEL','Search page:');
  126.     define('FORM_SEARCH_STRING_TITLE','Enter a search string');
  127.     define('FORM_SEARCH_SUBMIT','Submit');
  128.     define('FORM_PAGER_LABEL_BEFORE','Show');
  129.     define('FORM_PAGER_TITLE','Select records-per-page limit');
  130.     define('FORM_PAGER_LABEL_AFTER','records per page');
  131.     define('FORM_PAGER_SUBMIT','Apply');
  132.     define('FORM_PAGER_LINK','Show records from %d to %d');
  133.     define('FORM_RESULT_INFO','Records');
  134.     define('FORM_RESULT_SORTED_BY','Sorted by:');
  135.     define('TABLE_HEADING_PAGENAME','Page Name');
  136.     define('TABLE_HEADING_PAGENAME_TITLE','Sort by page name');
  137.     define('TABLE_HEADING_OWNER','Owner');
  138.     define('TABLE_HEADING_OWNER_TITLE','Sort by page owner');
  139.     define('TABLE_HEADING_LASTAUTHOR','Last Author');
  140.     define('TABLE_HEADING_LASTAUTHOR_TITLE','Sort by last author');
  141.     define('TABLE_HEADING_LASTEDIT','Last Edit');
  142.     define('TABLE_HEADING_LASTEDIT_TITLE','Sort by edit time');
  143.     define('TABLE_SUMMARY','List of pages on this server');
  144.     define('TABLE_HEADING_HITS_TITLE','Hits');
  145.     define('TABLE_HEADING_REVISIONS_TITLE','Sort by number of revisions (DEBUG ONLY)');
  146.     define('TABLE_HEADING_COMMENTS_TITLE','Comments');
  147.     define('TABLE_HEADING_BACKLINKS_TITLE','Backlinks');
  148.     define('TABLE_HEADING_REFERRERS_TITLE','Referrers');
  149.     define('TABLE_HEADING_HITS_ALT','Hits');
  150.     define('TABLE_HEADING_REVISIONS_ALT','Revisions');
  151.     define('TABLE_HEADING_COMMENTS_ALT','Comments');
  152.     define('TABLE_HEADING_BACKLINKS_ALT','Backlinks');
  153.     define('TABLE_HEADING_REFERRERS_ALT','Referrers');
  154.     define('TABLE_HEADING_ACTIONS','Actions');
  155.     define('ACTION_EDIT_LINK_TITLE','Edit %s');
  156.     define('ACTION_DELETE_LINK_TITLE','Delete %s');
  157.     define('ACTION_CLONE_LINK_TITLE','Clone %s');
  158.     define('ACTION_RENAME_LINK_TITLE','Rename %s (DISABLED)');
  159.     define('ACTION_ACL_LINK_TITLE','Change Access Control List for %s');
  160.     define('ACTION_INFO_LINK_TITLE','Display information and statistics for %s');
  161.     define('ACTION_EDIT_LINK','edit');
  162.     define('ACTION_DELETE_LINK','delete');
  163.     define('ACTION_CLONE_LINK','clone');
  164.     define('ACTION_RENAME_LINK','rename');
  165.     define('ACTION_ACL_LINK','acl');
  166.     define('ACTION_INFO_LINK','info');
  167.     define('TAKE_OWNERSHIP_LINK','Take ownership of');
  168.     define('NO_OWNER','(Nobody)');
  169.     define('TABLE_CELL_HITS_TITLE','Hits for %s (%d)');
  170.     define('TABLE_CELL_REVISIONS_TITLE','Display revisions for %s (%d)');
  171.     define('TABLE_CELL_COMMENTS_TITLE','Display comments for %s (%d)');
  172.     define('TABLE_CELL_BACKLINKS_TITLE','Display pages linking to %s (%d)');
  173.     define('TABLE_CELL_REFERRERS_TITLE','Display external sites linking to %s (%d)');
  174.     define('SELECT_RECORD_TITLE','Select %s');
  175.     define('NO_EDIT_NOTE','[No edit note]');
  176.     define('CHECK_ALL_TITLE','Check all records');
  177.     define('CHECK_ALL','Check all');
  178.     define('UNCHECK_ALL_TITLE','Uncheck all records');
  179.     define('UNCHECK_ALL','Uncheck all');
  180.     define('FORM_MASSACTION_LEGEND','Mass-action');
  181.     define('FORM_MASSACTION_LABEL','With selected');
  182.     define('FORM_MASSACTION_SELECT_TITLE','Choose action to apply to selected records (DISABLED)');
  183.     define('FORM_MASSACTION_OPT_DELETE','Delete all');
  184.     define('FORM_MASSACTION_OPT_CLONE','Clone all');
  185.     define('FORM_MASSACTION_OPT_RENAME','Rename all');
  186.     define('FORM_MASSACTION_OPT_ACL','Change Access Control List');
  187.     define('FORM_MASSACTION_SUBMIT','Submit');
  188.     define('ERROR_NO_MATCHES','Sorry, there are no pages matching "%s"');
  189.    
  190.    
  191.     // -------------------------------------
  192.     // Initialize variables
  193.    
  194.     $r = 1; #initialize row counter
  195.     $r_color = ALTERNATE_ROW_COLOR; #get alternate row color option
  196.     $c_color = STAT_COLUMN_COLOR; #get column color option
  197.     // record dropdown
  198.     $page_limits = unserialize(DEFAULT_RECORDS_RANGE);
  199.     // pager
  200.     $prev = '';       
  201.     $next = '';       
  202.    
  203.     //override defaults with action parameters
  204.     if (is_array($vars)) {
  205.         foreach ($vars as $param => $value){
  206.             switch ($param) {
  207.                 case 'colcolor':
  208.                     $c_color = (preg_match('/[01]/',$value))? $value : STAT_COLUMN_COLOR;
  209.                     break;
  210.                 case 'rowcolor':
  211.                     $r_color = (preg_match('/[01]/',$value))? $value : ALTERNATE_ROW_COLOR;
  212.                     break;
  213.             }
  214.         }
  215.     }
  216.    
  217.     //perform mass-operations if required (forthcoming)
  218.     if (isset($_GET['action']))
  219.     {
  220.         if ($_GET['action'] == 'massdelete')
  221.         {
  222.             echo $this->Action('massdelete');
  223.         }
  224.         elseif ($_GET['action'] == 'massrename')
  225.         {
  226.             echo $this->Action('massrename');
  227.         }
  228.         elseif ($_GET['action'] == 'massacls')
  229.         {
  230.             echo $this->Action('massacls');
  231.         }
  232.     }
  233.     else
  234.     {
  235.         // process URL variables
  236.         # JW 2005-07-19 some modifications to avoid notices but these are still not actually secure
  237.  
  238.         // number of records per page
  239.         if (isset($_POST['l']))
  240.             $l = $_POST['l'];
  241.         elseif (isset($_GET['l']))
  242.             $l = $_GET['l'];
  243.         else
  244.             $l = DEFAULT_RECORDS_LIMIT;
  245.  
  246.         // sort field
  247.         $sort = (isset($_GET['sort'])) ? $_GET['sort'] : DEFAULT_SORT_FIELD;
  248.         // sort order
  249.         $d = (isset($_GET['d'])) ? $_GET['d'] : DEFAULT_SORT_ORDER;
  250.         // start record
  251.         $s = (isset($_GET['s'])) ? $_GET['s'] : DEFAULT_START;
  252.  
  253.         // search string
  254.         if (isset($_POST['q']))
  255.             $q = $_POST['q'];
  256.         elseif (isset($_GET['q']))
  257.             $q = $_GET['q'];
  258.         else
  259.             $q = DEFAULT_SEARCH;
  260.  
  261.         // select all    added JW 2005-07-19
  262.         $checked = '';
  263.         if (isset($_GET['selectall']))
  264.         {
  265.             $checked = (1 == $_GET['selectall']) ? ' checked="checked"' : '';
  266.         }
  267.  
  268.         // restrict MySQL query by search string    modified JW 2005-07-19
  269.         $where = ('' == $q) ? "`latest` = 'Y'" : "`tag` LIKE '%".$q."%' AND `latest` = 'Y'";
  270.         // get total number of pages
  271.         $numpages = $this->getCount('pages',$where);
  272.  
  273.         // print page header
  274.         echo $this->Format('==== '.PAGE_TITLE.' ==== --- ');
  275.  
  276.         // build pager form   
  277.         $form1 = $this->FormOpen('','','post','page_admin_panel');
  278.         $form1 .= '<fieldset><legend>'.FORM_LEGEND.'</legend>'."\n";
  279.         $form1 .= '<label for="q">'.FORM_SEARCH_STRING_LABEL.'</label> <input type ="text" id="q" name="q" title="'.FORM_SEARCH_STRING_TITLE.'" size="20" maxlength="50" value="'.$q.'"/> <input type="submit" value="'.FORM_SEARCH_SUBMIT.'" /><br />'."\n";
  280.         // ranged drop-down
  281.         $pages_opts = optionRanges($page_limits,$numpages,DEFAULT_MIN_RECORDS_DISPLAY);
  282.         $form1 .= '<label for="l">'.FORM_PAGER_LABEL_BEFORE.'</label> '."\n";
  283.         $form1 .= '<select name="l" id="l" title="'.FORM_PAGER_TITLE.'">'."\n";
  284.         // build drop-down
  285.         foreach ($pages_opts as $opt) {
  286.             $selected = ($opt == $l) ? ' selected="selected"' : '';
  287.             $form1 .= '<option value="'.$opt.'"'.$selected.'>'.$opt.'</option>'."\n";
  288.         }
  289.         $form1 .=  '</select> <label for="l">'.FORM_PAGER_LABEL_AFTER.'</label> <input type="submit" value="'.FORM_PAGER_SUBMIT.'" /><br />'."\n";
  290.  
  291.         // build pager links
  292.         if ($s > 0)
  293.             $prev = '<a href="' .$this->Href('','','l='.$l.'&sort='.$sort.'&d='.$d.'&s='.($s-$l)).'&q='.$q.'" title="'.sprintf(FORM_PAGER_LINK, ($s-$l+1), $s).'">'.($s-$l+1).'-'.$s.'</a> |  '."\n";
  294.         if ($numpages > ($s + $l))
  295.             $next = ' | <a href="'.$this->Href('','','l='.$l.'&sort='.$sort.'&d='.$d.'&s='.($s+$l)).'&q='.$q.'" title="'.sprintf(FORM_PAGER_LINK, ($s+$l+1), ($s+2*$l)).'">'.($s+$l+1).'-'.($s+2*$l).'</a>'."\n";
  296.         $form1 .= FORM_RESULT_INFO.' ('.$numpages.'): '.$prev.($s+1).'-'.($s+$l).$next.'<br />'."\n";
  297.         $form1 .= '('.FORM_RESULT_SORTED_BY.'<em>'.$sort.', '.$d.'</em>)'."\n";
  298.         $form1 .= '</fieldset>'.$this->FormClose()."\n";
  299.  
  300.         // print form
  301.         echo $form1;
  302.  
  303.         // sort by counted values
  304.         switch($sort)
  305.         {
  306.             case 'edits': #alpha --- 'latest' needs to be disabled
  307.                 //sample query:
  308.                 //SELECT *, COUNT(*) as edits FROM `wikka1160_pages` GROUP BY tag ORDER BY edits DESC
  309.                 $count = ', COUNT(*) as edits';
  310.                 $group = 'GROUP BY tag';   
  311.                 $where = '1';
  312.                 //$where = ('' == $q) ? "1" : "`tag` LIKE '%".$q."%'";
  313.                 $table = 'pages';   
  314.                 break;
  315.             case 'comments': #to implement
  316.             /*
  317.                 // SELECT wikka1160_pages.tag, COUNT(  *  )  AS comments FROM wikka1160_pages, wikka1160_comments WHERE wikka1160_pages.tag = wikka1160_comments.page_tag GROUP  BY wikka1160_pages.tag ORDER  BY comments DESC
  318.                 $count = ', COUNT(*) as edits';
  319.                 $group = 'GROUP BY tag';   
  320.                 $where = '1';
  321.             */   
  322.                 break;
  323.             default:
  324.                 $table = 'pages';   
  325.         }
  326.  
  327.  
  328.         // get page list    
  329.         $pagedata = $this->LoadAll("SELECT *".$count." FROM ".$this->config["table_prefix"].$table." WHERE ".
  330.         $where." ".$group." ORDER BY ".$sort." ".$d." LIMIT ".$s.", ".$l);
  331.  
  332.         if ($pagedata)
  333.         {
  334.             // build table headers
  335.             $tagheader = '<a href="'.$this->Href('','', (($sort == 'tag' && $d == 'asc')? 'l='.$l.'&sort=tag&d=desc&q='.$q : 'l='.$l.'&sort=tag&d=asc&q='.$q)).'" title="'.TABLE_HEADING_PAGENAME_TITLE.'">'.TABLE_HEADING_PAGENAME.'</a>';
  336.             $ownerheader = '<a href="'.$this->Href('','', (($sort == 'owner' && $d == 'asc')? 'l='.$l.'&sort=owner&d=desc&q='.$q : 'l='.$l.'&sort=owner&d=asc&q='.$q)).'" title="'.TABLE_HEADING_OWNER_TITLE.'">'.TABLE_HEADING_OWNER.'</a>';
  337.             $userheader = '<a href="'.$this->Href('','', (($sort == 'user' && $d == 'asc')? 'l='.$l.'&sort=user&d=desc&q='.$q : 'l='.$l.'&sort=user&d=asc&q='.$q)).'" title="'.TABLE_HEADING_LASTAUTHOR_TITLE.'">'.TABLE_HEADING_LASTAUTHOR.'</a>';
  338.             $lasteditheader = '<a href="'.$this->Href('','', (($sort == 'time' && $d == 'desc')? 'l='.$l.'&sort=time&d=asc&q='.$q : 'l='.$l.'&sort=time&d=desc&q='.$q)).'" title="'.TABLE_HEADING_LASTEDIT_TITLE.'">'.TABLE_HEADING_LASTEDIT.'</a>';
  339.             $revisionsheader = '<a href="'.$this->Href('','', (($sort == 'edits' && $d == 'desc')? 'l='.$l.'&sort=edits&d=asc&q='.$q : 'l='.$l.'&sort=edits&d=desc&q='.$q)).'" title="'.TABLE_HEADING_REVISIONS_TITLE.'"><img src="'.REVISIONS_ICON.'" alt="'.TABLE_HEADING_REVISIONS_ALT.'"/></a>';
  340.  
  341.             $htmlout = "<table summary=\"".TABLE_SUMMARY."\" border=\"1px\" id=\"admin_table\">\n".
  342.             "<thead>\n<tr>\n".
  343.             "    <th> </th>\n".
  344.             "    <th>".$tagheader."</th>\n".
  345.             "    <th>".$ownerheader."</th>\n".
  346.             "    <th>".$userheader."</th>\n".
  347.             "    <th>".$lasteditheader."</th>\n".
  348.             "    <th class=\"number ".(($c_color == 1)? ' c1' : '')."\" title=\"".TABLE_HEADING_HITS_TITLE."\"><img src=\"".HITS_ICON."\" alt=\"".TABLE_HEADING_HITS_ALT."\"/></th>\n".
  349.             "    <th class=\"number ".(($c_color == 1)? ' c2' : '')."\" title=\"".TABLE_HEADING_REVISIONS_TITLE."\">".$revisionsheader."</th>\n".
  350.             "    <th class=\"number ".(($c_color == 1)? ' c3' : '')."\" title=\"".TABLE_HEADING_COMMENTS_TITLE."\"><img src=\"".COMMENTS_ICON."\" alt=\"".TABLE_HEADING_COMMENTS_ALT."\"/></th>\n".
  351.             "    <th class=\"number ".(($c_color == 1)? ' c4' : '')."\" title=\"".TABLE_HEADING_BACKLINKS_TITLE."\"><img src=\"".BACKLINKS_ICON."\" alt=\"".TABLE_HEADING_BACKLINKS_ALT."\"/></th>\n".
  352.             "    <th class=\"number ".(($c_color == 1)? ' c5' : '')."\" title=\"".TABLE_HEADING_REFERRERS_TITLE."\"><img src=\"".REFERRERS_ICON."\" alt=\"".TABLE_HEADING_REFERRERS_ALT."\"/></th>\n".
  353.             "    <th class=\"center\">".TABLE_HEADING_ACTIONS."</th>\n".
  354.             "  </tr>\n</thead>\n";
  355.  
  356.             // feed table with data
  357.             foreach($pagedata as $page)
  358.             {
  359.                 // truncate long page names
  360.                 $pagename = (strlen($page['tag']) > DEFAULT_TAG_LENGTH) ? substr($page['tag'], 0, DEFAULT_TAG_LENGTH).DEFAULT_TERMINATOR : $page['tag'];
  361.  
  362.                 // build handler links
  363.                 $lastedit = $page['time'];
  364.                 if ($pagename != $page['tag'])
  365.                 {
  366.                     $showpage = '<a href="'.$this->Href('',$page['tag'], '').'" title="'.$page['tag'].'">'.$pagename.'</a>';
  367.                 }
  368.                 else
  369.                 {
  370.                     $showpage = '<a href="'.$this->Href('',$page['tag'], '').'">'.$pagename.'</a>';
  371.                 }
  372.                 $editpage = '<a href="'.$this->Href('edit',$page['tag'], '').'" title="'.sprintf(ACTION_EDIT_LINK_TITLE, $page['tag']).'">'.ACTION_EDIT_LINK.'</a>';
  373.                 $deletepage = '<a href="'.$this->Href('delete',$page['tag'], '').'" title="'.sprintf(ACTION_DELETE_LINK_TITLE, $page['tag']).'">'.ACTION_DELETE_LINK.'</a>';
  374.                 $clonepage = '<a href="'.$this->Href('clone',$page['tag'], '').'" title="'.sprintf(ACTION_CLONE_LINK_TITLE, $page['tag']).'">'.ACTION_CLONE_LINK.'</a>';
  375.                 // renaming disabled
  376.                 $renamepage = '<a href="'.$this->Href('rename',$page['tag'], '').'" title="'.sprintf(ACTION_RENAME_LINK_TITLE, $page['tag']).'">'.ACTION_RENAME_LINK.'</a>';
  377.                 $aclpage = '<a href="'.$this->Href('acls',$page['tag'], '').'" title="'.sprintf(ACTION_ACL_LINK_TITLE, $page['tag']).'">'.ACTION_ACL_LINK.'</a>';
  378.                 $infopage = '<a href="'.$this->Href('info',$page['tag'], '').'" title="'.sprintf(ACTION_INFO_LINK_TITLE, $page['tag']).'">'.ACTION_INFO_LINK.'</a>';
  379.  
  380.                 // get page owner
  381.                 if ($page['owner'])
  382.                 {
  383.                     // is the owner a registered user?
  384.                     if ($this->LoadUser($page['owner']))
  385.                     {
  386.                         // does user's homepage exist?
  387.                         if ($this->ExistsPage($page