Files
selima-perl/lib/php/monica/list.inc.php
2026-03-10 21:31:43 +08:00

3775 lines
131 KiB
PHP

<?php
// File name: list.inc.php
// Description: PHP subroutines to handle the item list
// Date: 2002-12-26
// Author: imacat <imacat@pristine.com.tw>
// Copyright: Copyright (C) 2002-2013 Pristine Communications
// This file is in UTF-8 萬國碼
// Set the include path
if (!defined("INCPATH_SET")) {
require_once dirname(__FILE__) . "/incpath.inc.php";
}
// Referenced subroutines
require_once "monica/a2html.inc.php";
require_once "monica/actlog.inc.php";
require_once "monica/addget.inc.php";
require_once "monica/addslash.inc.php";
require_once "monica/chkfunc.inc.php";
require_once "monica/commtext.inc.php";
require_once "monica/echoform.inc.php";
require_once "monica/errmsg.inc.php";
require_once "monica/formfunc.inc.php";
require_once "monica/getlang.inc.php";
require_once "monica/gettext.inc.php";
require_once "monica/htmlchar.inc.php";
require_once "monica/listpref.inc.php";
require_once "monica/lninfo.inc.php";
require_once "monica/login.inc.php";
require_once "monica/markabbr.inc.php";
require_once "monica/pagefunc.inc.php";
require_once "monica/pic.inc.php";
require_once "monica/requri.inc.php";
require_once "monica/runcmd.inc.php";
require_once "monica/sql.inc.php";
require_once "monica/sqlconst.inc.php";
require_once "monica/userpref.inc.php";
// _list_cmp_range: Compare the abstract ranges for usort()
function _list_cmp_range($a, $b)
{
if ($a["start"] != $a["end"]) {
return $a["start"] - $b["start"];
} else {
return $a["end"] - $b["end"];
}
}
// _list_cmp_query: Compare the query phrases for usort()
function _list_cmp_query($a, $b)
{
return mb_strlen($b) - mb_strlen($a);
}
// list_type: Return the list name
function list_type($type = null)
{
// Cache the result
static $cache;
// Set the list type
if (!is_null($type)) {
$cache = $type;
}
// Return the cache
if (isset($cache)) {
return $cache;
}
// Obtain the current form
$FORM =& curform();
// Form type specified in arguments
if (array_key_exists("list", $FORM)) {
$cache = $FORM["list"];
// No form source is found
} else {
$cache = null;
}
return $cache;
}
// parse_query: Parse the query string into multiple search phrases
function parse_query($query)
{
// Cache the result
static $cache = array();
// Return the cache
if (array_key_exists($query, $cache)) {
return $cache[$query];
}
$phrases = array();
$query = trim($query);
while ($query != "") {
// Non-quoted word
if (preg_match("/^([^\s\"']+)\s*(.*?)$/", $query, $m)) {
$phrases[] = $m[1];
$query = $m[2];
// Double-quoted string
} elseif (preg_match("/^(?:\"((?:[^\\\\\"]|\\\\.)+)\"?)\s*(.*?)$/", $query, $m)) {
$m[1] = str_replace("$", "\\$", $m[1]);
eval("\$phrases[] = \"$m[1]\";");
$query = $m[2];
// Single-quoted string
} elseif (preg_match("/^(?:'((?:[^\\\\']|\\\\.)+)'?)\s*(.*?)$/", $query, $m)) {
eval("\$phrases[] = '$m[1]';");
$query = $m[2];
// Empty quoted strings
} elseif (preg_match("/^(?:\"\"?|''?)\s*(.*?)$/", $query, $m)) {
$query = $m[1];
}
}
sort($phrases);
// Cache it
$cache[$query] = $phrases;
return $phrases;
}
// urlcheck: Perform URL. checks on the current list
function urlcheck(&$current)
{
// Check the URL. format and gather those to check the availibility.
$tocheck = array();
$stdin = "";
for ($i = 0; $i < count($current); $i++) {
if (is_null($current[$i]["_urlcheck"])) {
$current[$i]["_urlcheck"] = t_notset();
} elseif (!is_url_wellformed($current[$i]["_urlcheck"])) {
$current[$i]["_urlcheck"] = C_("Malformed");
} else {
$tocheck[count($tocheck)] =& $current[$i];
$stdin .= $current[$i]["_urlcheck"] . "\n";
}
}
// Nothing to check further
if (count($tocheck) == 0) {
return;
}
// Preserve the original timeout
$timeout = ini_get("max_execution_time");
ini_set("max_execution_time", 0);
// Run the command and obtain the output
$cmd = array(dirname(__FILE__) . "/urlcheck");
$out = xruncmd($cmd, $stdin);
// Restore the timeout
ini_set("max_execution_time", $timeout);
// Save the result
$result = explode("\n", $out);
for ($i = 0; $i < count($tocheck); $i++) {
$tocheck[$i]["_urlcheck"] = $result[$i]?
C_("OK"): C_("Unreachable");
}
return;
}
/////////////////////////
// New Object-Oriented List Handler
// By imacat 2004-05-30
/////////////////////////
// BaseList: Base list handler class
class BaseList
{
// Parameters to be set by the user
// The default number of rows per page when user preference is unavailable.
// Don't set to null.
// This is not to set the number of rows. Set $_pagesize instead.
protected $_DEFAULT_LIST_SIZE = 10;
protected $_DEFAULT_LIST_COLS = array("sn");
// The default sort order -- for non-VIEW lists only
protected $_DEFAULT_SORTBY = null;
// The list brief size
protected $_DEFAULT_BRIEF_LEN = 15;
// The query abstract span from the found phrase
protected $_QABS_SPAN = 30;
// The maximum query abstract length
protected $_QABS_MAXLEN = 200;
// The picture thumbnail size
protected $_PIC_THUMBNAIL_SIZE = 70;
// Default settings
// Known columns that should not be displayed (has a special purpose)
protected $_COLS_NO_DISPLAY = array("_viewurl", "_sel", "_selurl", "_statord");
// Known columns that should never be searched against
protected $_COLS_NO_SEARCH = array("pic", "att", "pdf", "_urlcheck", "_viewurl", "_sel", "_selurl", "_statord");
// Known columns that should not be sorted with
protected $_COLS_NO_SORT_BY = array("_urlcheck", "_viewurl", "_sel", "_selurl", "_statord");
// Columns that should display its brief instead
protected $_COLS_BRIEF = array();
// The page title for the current list
public $title = null;
// The error status after fetching the list
public $error = null;
// The switch for different lists
public $lists_switch = null;
// The number of total/matching records
public $total = null;
// Whether we have fetched the list
protected $_fetched = false;
// Whether we need mass deletion checkers
protected $_massdel = false;
// Whether we need preceding numbering
protected $_nonumber = false;
// Whether we need selection links
protected $_noselect = false;
// Whether we need sorting links
protected $_nosortby = false;
// Whether the list should be in a reversed order
protected $_reverse = false;
// Whether these are static pages
protected $_static = false;
// The file name pattern of the static pages
protected $_static_filepat = "%04d.html";
protected $_static_lastfile = "last.html";
// Query arguments
protected $_form = null;
protected $_query = null;
protected $_pageno = null;
protected $_sortby = null;
protected $_limit = null;
// Select parameters
protected $_is_called_form = null;
protected $_caller = null;
protected $_cformid = null;
// The language to use
protected $_lang = null;
// If this is a multi-lingual table
protected $_is_ml_table = null;
// Column labels to be used in _html_list() and _html_listprefform()
protected $_col_labels = array();
// This shall be set when initializing the handler
protected $_useview;
protected $_seltext;
protected $_selurl_tmpl;
// The parsing results
protected $_table = null;
protected $_view = null;
protected $_select = null;
protected $_select_total = null;
protected $_current = null;
protected $_cols = null;
protected $_lastpage = null;
// The number of rows per page. Set to false to disable paging.
protected $_pagesize = null;
protected $_startno = null;
protected $_endno = null;
// Intermediate parsing results when fetching a list
protected $_coldefs = array();
protected $_sortkeys = array();
protected $_query_phrases = array();
protected $_listcols = array();
// __construct: Initialize the handler
// We only set up the environment, but do not really initialize
// the object here. This way we can configure the environment
// in the beginning before we pass its arguments in the middle
// of the script
function __construct($FORM, $table)
{
// The default value
if (is_null($FORM)) {
$FORM = curform();
}
// Set the environment
if ($GLOBALS["SQL_DBTYPE"] != SQL_NONE) {
$this->_useview = sql_support(SQL_FEATURE_VIEW);
}
// Set the parameters
$this->_form =& $FORM;
$this->_table = $table;
$this->_pageno = array_key_exists("pageno", $this->_form)?
$this->_form["pageno"]: null;
$this->_sortby = array_key_exists("sortby", $this->_form)?
$this->_form["sortby"]: null;
$this->_query = array_key_exists("query", $this->_form)?
$this->_form["query"]: null;
if ($this->_query == C_("(query phrase)")) {
$this->_query = "";
}
$this->_lang = array_key_exists("lang", $this->_form)
&& in_array($this->_form["lang"], $GLOBALS["ALL_LINGUAS"])?
$this->_form["lang"]: getlang();
// The default column labels
$this->_col_labels(array(
// Common labels shared by all list handlers
"sn" => C_("S/N"),
"created" => C_("Created"),
"createdby" => C_("Created by"),
"updated" => C_("Updated"),
"updatedby" => C_("Updated by"),
// Other commonly-seen column labels
"body" => C_("Content"),
"cat" => C_("Category"),
"cov" => C_("Coverage"),
"date" => C_("Date"),
"disabled" => C_("Disabled?"),
"dsc" => C_("Description"),
"email" => C_("E-mail"),
"hid" => C_("Hidden?"),
"html" => C_("HTML?"),
"id" => C_("ID."),
"kw" => C_("Keywords"),
"name" => C_("Name"),
"ord" => C_("Order"),
"path" => C_("Page path"),
"pic" => C_("Picture"),
"picratio" => C_("Pic. ratio"),
"piccap" => C_("Pic. caption"),
"picpos" => C_("Pic. position"),
"subject" => C_("Subject"),
"title" => C_("Title"),
"url" => C_("URL."),
"_urlcheck" => C_("Status (slow)"),
));
// Parameters for the called forms
$this->_is_called_form = array_key_exists("caller", $this->_form)
&& array_key_exists("cformid", $this->_form);
if ($this->_is_called_form) {
$this->_caller = $this->_form["caller"];
$this->_cformid = $this->_form["cformid"];
$this->_seltext = C_("Select");
$this->_selurl_tmpl = $this->_caller
. "?formid=" . $this->_cformid . "&selsn=%d";
$this->_title = C_("Select a Data Record");
} else {
$this->_caller = null;
$this->_cformid = null;
$this->_seltext = C_("Edit");
$this->_selurl_tmpl = REQUEST_FILE . "?form=cur&sn=%d";
$this->_title = C_("Manage Data");
}
// The default of the multi-lingual status
$this->_is_ml_table = null;
}
// fetch: Fetch the current list.
// We dispatch here for different query engines
function fetch()
{
// Fetched before
if ($this->_fetched) {
return $this->error;
}
$this->_fetched = true;
// Initialize the error status
$this->error = null;
switch ($GLOBALS["SQL_DBTYPE"]) {
case SQL_MYSQL:
return $this->_fetch_offset();
case SQL_POSTGRESQL:
return $this->_fetch_once();
}
}
// page_param: Obtain page parameters
function page_param()
{
// Fetch the current list if not fetched yet
if (!$this->_fetched) {
$this->fetch();
}
// Don't show the list
if (is_null($this->total)) {
return null;
}
// No record to be listed
if ($this->total == 0) {
return null;
}
$args = array();
$baseurl = rem_get_arg(REQUEST_FILEQS, "pageno");
// The first page -- only meaningful when there is more than one page
if ($this->_lastpage > 1) {
if ($this->_static) {
$args["first"] = sprintf($this->_static_filepat, 1);
} elseif ($this->_reverse) {
$args["first"] = add_get_arg($baseurl, "pageno", 1, DUP_OK);
} else {
$args["first"] = $baseurl;
}
}
// The previous page
if ($this->_pageno > 1) {
if ($this->_static) {
$args["prev"] = sprintf($this->_static_filepat, $this->_pageno - 1);
} elseif ($this->_reverse || $this->_pageno - 1 != 1) {
$args["prev"] = add_get_arg($baseurl, "pageno", $this->_pageno - 1, DUP_OK);
} else {
$args["prev"] = $baseurl;
}
}
// The next page
if ($this->_pageno < $this->_lastpage) {
if ($this->_static) {
if ( !is_null($this->_static_lastfile)
&& $this->_pageno + 1 == $this->_lastpage) {
$args["next"] = $this->_static_lastfile;
} else {
$args["next"] = sprintf($this->_static_filepat, $this->_pageno + 1);
}
} elseif (!$this->_reverse || $this->_pageno + 1 != $this->_lastpage) {
$args["next"] = add_get_arg($baseurl, "pageno", $this->_pageno + 1, DUP_OK);
} else {
$args["next"] = $baseurl;
}
}
// The last page -- only meaningful when there is more than one page
if ($this->_lastpage > 1) {
if ($this->_static) {
if (!is_null($this->_static_lastfile)) {
$args["last"] = $this->_static_lastfile;
} else {
$args["last"] = sprintf($this->_static_filepat, $this->_lastpage);
}
} elseif (!$this->_reverse) {
$args["last"] = add_get_arg($baseurl, "pageno", $this->_lastpage, DUP_OK);
} else {
$args["last"] = $baseurl;
}
}
return $args;
}
// html: Output the list
function html()
{
// Fetch the current list if not fetched yet
if (!$this->_fetched) {
$this->fetch();
}
// Display the title
$this->_html_title();
// Display the error message
$this->_html_errmsg();
// Display the switch for different lists
$this->_html_lists_switch();
// Display a link to add a new item
$this->_html_newlink();
// Display the search box
$this->_html_search();
// Display the list status message
$this->_html_liststat();
// Display the page bar at the beginning
$this->_html_pagebar();
// List the items
$this->_html_list();
// Display the page bar at the end
$this->_html_pagebar();
// Display a form to change the list preference
$this->_html_listprefform();
return;
}
// set_listpref: Set the list preference
function set_listpref()
{
$handler = new ListPreference($this->_form);
$handler->main();
}
/////////////////////////
// Methods belows are private. Do not call them directly.
// Override them when needed.
/////////////////////////
// _fetch_once: Fetch the current list in once.
// Fetching the list in one query: Query everything, fetch
// the total and only the wanted portion.
// This is faster in PostgreSQL but slower in MySQL.
function _fetch_once()
{
// See if we need to use views or not.
// Views make things much faster and easier, but some DBMS has no views.
if ($this->_useview) {
$r = $this->_select_with_view();
} else {
$r = $this->_select_without_view();
}
$this->_select = sprintf("SELECT %s FROM %s%s%s%s;\n",
$r["cols"], $r["table"], $r["where"], $r["orderby"], $r["limit"]);
$result = sql_query($this->_select);
$this->total = sql_num_rows($result);
// The number of rows per page
if (is_null($this->_pagesize)) {
$this->_pagesize = userpref("listsize", get_class($this));
if (is_null($this->_pagesize)) {
$this->_pagesize = $this->_DEFAULT_LIST_SIZE;
}
}
// Paging not in use
if ($this->_pagesize === false) {
$this->_lastpage = 1;
$this->_startno = 0;
$this->_endno = $this->total - 1;
// If endno is -1 (when total is 0), set to 0
if ($this->_endno < 0) {
$this->_endno = 0;
}
// Fetch everything
for ($i = 0, $this->_current = array(); $i < $this->total; $i++) {
$this->_current[] = sql_fetch_assoc($result);
}
// Set the columns to be displayed
$this->_check_listcols();
// Done
return $this->error;
}
$this->_lastpage = floor(($this->total - 1) / $this->_pagesize) + 1;
// The output type of floor() is float
settype($this->_lastpage, "integer");
// If last page is 0 (when total is 0), set to page 1
if ($this->_lastpage < 1) {
$this->_lastpage = 1;
}
// Check the page number
$error = $this->_check_pageno();
if (!is_null($error) && is_null($this->error)) {
$this->error = $error;
}
// Calculate the start and end record number
$this->_startno = ($this->_pageno - 1) * $this->_pagesize;
$this->_endno = $this->_pageno * $this->_pagesize - 1;
// If there are not enough remaining records, set to the last one
if ($this->_endno > $this->total - 1) {
$this->_endno = $this->total - 1;
}
// If the last record is -1 (when total is 0), set to 0
if ($this->_endno < 0) {
$this->_endno = 0;
}
// Go to that page
$this->_current = array();
// If not empty
if ($this->total > 0) {
// Move to startno
sql_seek($result, $this->_startno);
// Fetch until endno
for ($i = $this->_startno; $i <= $this->_endno; $i++) {
$this->_current[] = sql_fetch_assoc($result);
}
}
// Set the columns to be displayed
$this->_check_listcols();
// Done
return $this->error;
}
// _fetch_offset: Fetch the current list with LIMIT and OFFSET.
// Fetching the list in 2 queries: First query the total with count(*)
// and then query only the wanted portion with LIMIT and OFFSET.
// This is faster in MySQL but slower in PostgreSQL.
function _fetch_offset()
{
// See if we need to use views or not.
// Views make things much faster and easier, but some DBMS has no views.
if ($this->_useview) {
$r = $this->_select_with_view();
} else {
$r = $this->_select_without_view();
}
// The number of rows per page
if (is_null($this->_pagesize)) {
$this->_pagesize = userpref("listsize", get_class($this));
if (is_null($this->_pagesize)) {
$this->_pagesize = $this->_DEFAULT_LIST_SIZE;
}
}
// Paging not in use
if ($this->_pagesize === false) {
$this->_select = sprintf("SELECT %s FROM %s%s%s%s;\n",
$r["cols"], $r["table"], $r["where"], $r["orderby"], $r["limit"]);
$result = sql_query($this->_select);
// Fetch everything
for ($i = 0, $this->_current = array(); $i < $this->total; $i++) {
$this->_current[] = sql_fetch_assoc($result);
}
$this->total = sql_num_rows($result);
$this->_lastpage = 1;
$this->_startno = 0;
$this->_endno = $this->total - 1;
// If endno is -1 (when total is 0), set to 0
if ($this->_endno < 0) {
$this->_endno = 0;
}
// Set the columns to be displayed
$this->_check_listcols();
// Done
return $this->error;
}
// Obtain the total number
$this->_select_total = sprintf("SELECT count(*) AS count FROM %s%s%s;\n",
$r["table"], $r["where"], $r["limit"]);
$result = sql_query($this->_select_total);
$row = sql_fetch_assoc($result);
$this->total = $row["count"];
$this->_lastpage = floor(($this->total - 1) / $this->_pagesize) + 1;
// The output type of floor() is float
settype($this->_lastpage, "integer");
// If last page is 0 (when total is 0), set to page 1
if ($this->_lastpage < 1) {
$this->_lastpage = 1;
}
// Check the page number
$error = $this->_check_pageno();
if (!is_null($error) && is_null($this->error)) {
$this->error = $error;
}
// Calculate the start and end record number
$this->_startno = ($this->_pageno - 1) * $this->_pagesize;
$this->_endno = $this->_pageno * $this->_pagesize - 1;
// If there are not enough remaining records, set to the last one
if ($this->_endno > $this->total - 1) {
$this->_endno = $this->total - 1;
}
// If the last record is -1 (when total is 0), set to 0
if ($this->_endno < 0) {
$this->_endno = 0;
}
// Obtain everything in this page
$this->_current = array();
if (!$this->_reverse) {
$this->_select = sprintf("SELECT %s FROM %s%s%s LIMIT %d OFFSET %d;\n",
$r["cols"], $r["table"], $r["where"], $r["orderby"],
$this->_endno - $this->_startno + 1,
$this->_startno);
} else {
$this->_select = sprintf("SELECT %s FROM %s%s%s LIMIT %d OFFSET %d;\n",
$r["cols"], $r["table"], $r["where"], $r["orderby"],
$this->_endno - $this->_startno + 1,
$this->total - $this->_endno - 1);
}
// If not empty
if ($this->total > 0) {
$result = sql_query($this->_select);
$count = sql_num_rows($result);
for ($i = 0; $i < $count; $i++) {
$this->_current[] = sql_fetch_assoc($result);
}
}
// Set the columns to be displayed
$this->_check_listcols();
// Done
return $this->error;
}
// _sql_cols: Obtain the SQL columns list phase
function _sql_cols()
{
// Obtain the columns to list
for ( $i = 0, $this->_coldefs = array(), $cols = array();
$i < count($this->_cols); $i++) {
$def = $this->_coldef($this->_cols[$i]);
$this->_coldefs[] = array(
"def" => $def,
"alias" => $this->_cols[$i]);
$cols[] = $def . " AS " . $this->_cols[$i];
}
return implode(", ", $cols);
}
// _coldef: Column definition for non-view usage
function _coldef($col)
{
// Obtain the column definition
switch ($col) {
case "createdby":
case "updatedby":
return $col . ".name";
default:
// Multi-lingual columns
if (in_array($col, sql_cols_ml($this->_table))) {
// Default language
if ($this->_lang == DEFAULT_LANG) {
return $this->_table . "." . $col . "_"
. ln($this->_lang, LN_DATABASE);
// Fall back to the default language
} else {
$thiscol = $this->_table . "." . $col . "_"
. ln($this->_lang, LN_DATABASE);
$defcol = $this->_table . "." . $col . "_"
. ln(DEFAULT_LANG, LN_DATABASE);
return "COALESCE(" . $thiscol . ", " . $defcol . ")";
}
// Ordinary columns
} else {
return $this->_table . "." . $col;
}
}
}
// _sql_join: Get the SQL JOIN phase
function _sql_join()
{
$join = "";
$cols = sql_cols_nl($this->_table);
if (in_array("createdby", $cols)) {
$join .= " LEFT JOIN users AS createdby ON "
. $this->_table . ".createdby=createdby.sn";
}
if (in_array("updatedby", $cols)) {
$join .= " LEFT JOIN users AS updatedby ON "
. $this->_table . ".updatedby=updatedby.sn";
}
return $join;
}
// _liststat_message: Return the current list statistics message
function _liststat_message()
{
// No record to list
if ($this->total == 0) {
// Empty comes from a query
if (!is_null($this->_query)) {
return C_("Nothing found. Please try another query.");
// Empty database
} else {
return C_("The database is empty.");
}
// Fit in one page
} elseif ($this->_pagesize === false || $this->total <= $this->_pagesize) {
// Result comes from a query
if (!is_null($this->_query)) {
return sprintf(dngettext(COMMONDOMAIN,
"Your query found %s record.",
"Your query found %s records.",
$this->total),
number_format($this->total));
// List result
} else {
return sprintf(dngettext(COMMONDOMAIN,
"%s record.",
"%s records.",
$this->total),
number_format($this->total));
}
// More than one page
} else {
if (!is_null($this->_query)) {
return sprintf(dngettext(COMMONDOMAIN,
"Your query found %s record, listing %s to %s.",
"Your query found %s records, listing %s to %s.",
$this->total),
number_format($this->total),
number_format($this->_startno+1),
number_format($this->_endno+1));
// List result
} else {
return sprintf(dngettext(COMMONDOMAIN,
"%s record, listing %s to %s.",
"%s records, listing %s to %s.",
$this->total),
number_format($this->total),
number_format($this->_startno+1),
number_format($this->_endno+1));
}
}
}
// _echo_colval: Output a list column value
function _echo_colval($col, &$row)
{
// Null/no value
if (is_null($row[$col])) {
echo h_abbr(t_notset());
// A brief should be displayed instead
} elseif ( in_array($col, $this->_COLS_BRIEF)
&& mb_strlen($row[$col]) > $this->_DEFAULT_BRIEF_LEN) {
// Strip the HTML tags
$text = $row[$col];
if ( array_key_exists("html", $row)
&& $row["html"]) {
$text = strip_tags($text);
}
echo h(mb_substr($text, 0, $this->_DEFAULT_BRIEF_LEN)) . "";
// Always display "pic" column as a thumbnail preview
} elseif ($col == "pic") {
$alt = C_("Picture preview");
$picid = readpic_content($row[$col],
array("max" => $this->_PIC_THUMBNAIL_SIZE),
$row["sn"], $this->_table);
$PICS =& pic_deposit();
$pic = $PICS[$picid];
echopic_thumbnail($pic, $alt);
// Always display "att" and "pdf" columns as their sizes
} elseif ($col == "att" || $col == "pdf") {
echo h_abbr(report_size(strlen($row[$col])));
// Always display "_urlcheck" column as URL. checking status
} elseif ($col == "_urlcheck") {
echo h($row[$col]);
// Ordinary columns
} else {
echo h($row[$col]);
}
return;
}
/////////////////////////
// Methods belows are private. Do not call them directly.
// Do not override them, either.
/////////////////////////
// _check_pageno: Check the page number
function _check_pageno()
{
// Save it elsewhere and replace with default value temporarily
$pageno = $this->_pageno;
$this->_pageno = !$this->_reverse? 1: $this->_lastpage;
// Page number not specified
if (is_null($pageno)) {
return null;
}
// Text string
if (is_string($pageno)) {
// If it is too long or too short
if (strlen($pageno) > 9) {
return array("msg"=>NC_("Page number (%s) invalid. Please specify a valid page number."),
"margs"=>array($pageno));
}
// If it is all-digits
if (!preg_match("/^\d+$/", $pageno)) {
return array("msg"=>NC_("Page number (%s) invalid. Please specify a valid page number."),
"margs"=>array($pageno));
}
// If it is all-digits
if (preg_match("/^0+$/", $pageno)) {
return array("msg"=>NC_("Page number (%s) invalid. Please specify a valid page number."),
"margs"=>array($pageno));
}
// Convert its type to integer
settype($pageno, "integer");
}
// Not an integer still
if (!is_int($pageno)) {
return array("msg"=>NC_("Page number (%s) invalid. Please specify a valid page number."),
"margs"=>array($pageno));
}
// Out of range
if (!is_null($this->_lastpage) && $pageno > $this->_lastpage) {
return array("msg"=>NC_("Page number (%d) out of range. Please specify a number between 1 and %d."),
"margs"=>array($pageno, $this->_lastpage));
}
// OK
$this->_pageno = $pageno;
return null;
}
// _select_with_view: Obtain the SQL statement with views
// This makes life easier *^_^*
function _select_with_view()
{
// Obtain the view name
if (is_null($this->_view)) {
$this->_view = $this->_table . "_list";
if (count($GLOBALS["ALL_LINGUAS"]) > 1) {
$this->_view .= "_" . ln($this->_lang, LN_DATABASE);
}
}
// Obtain the available columns
if (is_null($this->_cols)) {
$this->_cols = sql_cols($this->_view);
}
// Obtain the SQL WHERE phase
$where = $this->_sql_filter();
// Obtain the SQL ORDER BY phase
$orderby = $this->_sql_orderby();
// Obtain the LIMIT phase
$limit = !is_null($this->_limit)? " LIMIT " . $this->_limit: "";
// Compose the SQL query
return array(
"cols" => "*",
"table" => $this->_view,
"where" => $where,
"orderby" => $orderby,
"limit" => $limit,
);
}
// _select_without_view: Obtain the SQL statement manually without views
// SQL DBMS without views are to be cursed -- old MySQL does
function _select_without_view()
{
// Obtain the available columns
$this->_cols = sql_cols_nl($this->_table);
$this->_cols = array_diff($this->_cols, array("mtime"));
// _sql_cols() set the column definitions and may alter
// $this->_cols to to get the final columns list
$cols = $this->_sql_cols();
// Obtain the SQL JOIN phase
$join = $this->_sql_join();
// Obtain the SQL WHERE phase
$where = $this->_sql_filter();
// Obtain the SQL ORDER BY phase
$orderby = $this->_sql_orderby();
// Obtain the LIMIT phase
$limit = !is_null($this->_limit)? " LIMIT " . $this->_limit: "";
// Compose the SQL query
return array(
"cols" => $cols,
"table" => $this->_table . $join,
"where" => $where,
"orderby" => $orderby,
"limit" => $limit,
);
}
// _sql_filter: Get the SQL WHERE phase
// The returned SQL phrase is always in UTF-8
function _sql_filter()
{
// No query, return empty string
if (is_null($this->_query)) {
if ( method_exists($this, "_pre_filter")
&& !is_null($this->_pre_filter())) {
return " WHERE " . $this->_pre_filter();
}
return "";
}
// Regularize it
$this->_query = trim($this->_query);
// Check if it is filled
if ($this->_query == "") {
$this->error = array("msg"=>NC_("Please fill in your query."));
if ( method_exists($this, "_pre_filter")
&& !is_null($this->_pre_filter())) {
return " WHERE " . $this->_pre_filter();
}
return "";
}
$this->_query_phrases = parse_query($this->_query);
// Bounce if nothing to query
if (count($this->_query_phrases) == 0) {
if ( method_exists($this, "_pre_filter")
&& !is_null($this->_pre_filter())) {
return " WHERE " . $this->_pre_filter();
}
return "";
}
// Obtain the columns to query
if ($this->_useview) {
$cols = array_diff($this->_cols, $this->_COLS_NO_SEARCH);
// Use the column definition kept so far
} else {
for ($i = 0, $cols = array(); $i < count($this->_coldefs); $i++) {
// Columns that should not be searched against
if (in_array($this->_coldefs[$i]["alias"], $this->_COLS_NO_SEARCH)) {
continue;
}
$cols[] = $this->_coldefs[$i]["def"];
}
}
// Compose the query condition
$conds = array();
// Obtain each phase
foreach ($this->_query_phrases as $phrase) {
$subconds = array();
foreach ($cols as $col) {
if ($GLOBALS["SQL_DBTYPE"] == SQL_POSTGRESQL) {
$subconds[] = "cast($col AS text) ILIKE '%" . sql_esclike($phrase) . "%'";
} else {
$subconds[] = "cast($col AS text) LIKE '%" . sql_esclike($phrase) . "%'";
}
}
$conds[] = implode(" OR ", $subconds);
}
// Append the the pre-defined filter
if ( method_exists($this, "_pre_filter")
&& !is_null($this->_pre_filter())) {
$conds[] = $this->_pre_filter();
}
// Compose the statement
if (count($conds) == 1) {
$sql = $conds[0];
} else {
$conds0 = array();
foreach ($conds as $cond) {
$conds0[] = "($cond)";
}
$sql = implode(" AND ", $conds0);
}
// Append WHERE
return " WHERE " . $sql;
}
// _compose_query_key: Compose the query key from the query phrases
function _compose_query_key()
{
// Bounce if there is no query phrases
if (count($this->_query_phrases) == 0) {
return "";
}
for ($i = 0, $phrases = array(); $i < count($this->_query_phrases); $i++) {
$phreses[] = "\"" . addslashes($this->_query_phrases[$i]) . "\"";
}
return implode(",", $phreses);
}
// _sql_orderby: Get the SQL ORDER BY phase
function _sql_orderby()
{
// Parse the "sortby" argument
$this->_parse_sortby($this->_sortby);
// Check the sort keys, and empty them if invalid
$error = $this->_check_sortkeys();
if (!is_null($error)) {
if (is_null($this->error)) {
$this->error = $error;
}
$this->_sortkeys = array();
}
// Apply _DEFAULT_SORTBY if not in a view
if ( count($this->_sortkeys) == 0
&& !$this->_useview
&& !is_null($this->_DEFAULT_SORTBY)) {
// Parse the _DEFAULT_SORTBY argument
$this->_parse_sortby($this->_DEFAULT_SORTBY);
// Check the sort keys, and empty them if invalid
$error = $this->_check_sortkeys();
if (!is_null($error)) {
if (is_null($this->error)) {
$this->error = $error;
}
$this->_sortkeys = array();
}
}
// Set the "sortby" attribute
$this->_compose_sortby();
// Bounce if there is no sorting key
if (count($this->_sortkeys) == 0) {
return "";
}
// Obtain the corresponding SQL phrase
for ($i = 0, $phrases = array(); $i < count($this->_sortkeys); $i++) {
$phrases[] = $this->_sortkeys[$i]["sql"];
}
$sql = " ORDER BY " . implode(", ", $phrases);
return $sql;
}
// _parse_sortby: Parse the "sortby" argument
// $sortby argument should be specified as "key1,-key2,...",
// where initial minus (-) before the key means decreasing.
function _parse_sortby($sortby)
{
$this->_sortkeys = array();
// Bounce for nothing
if (is_null($sortby)) {
return;
}
$sortby = trim($sortby);
// Bounce if $sortby is empty
if ($sortby == "") {
return;
}
// Split by comma
$phrases = explode(",", $sortby);
for ($i = 0; $i < count($phrases); $i++) {
// Compose the sort key
$key = trim($phrases[$i]);
$desc = false;
$sql = $key;
// Check the decreasing flag with the initial "-" sign
if (substr($key, 0, 1) == "-") {
$key = trim(substr($key, 1));
$desc = true;
$sql = "$key DESC";
}
// Add this sort key
$this->_sortkeys[] = array(
"key" => $key,
"desc" => $desc,
"sql" => $sql,
);
}
return;
}
// _check_sortkeys: Check if the sorting keys are valid
function _check_sortkeys()
{
// Skip if nothing to check
if (count($this->_sortkeys) == 0) {
return null;
}
// Obtain the valid sorting keys
if ($this->_useview) {
$validkeys = array_diff($this->_cols, $this->_COLS_NO_SORT_BY);
// Check each candidate
for ($i = 0; $i < count($this->_sortkeys); $i++) {
if (!in_array($this->_sortkeys[$i]["key"], $validkeys)) {
return array("msg"=>NC_("You cannot sort by \"%s\"."),
"margs"=>array($this->_sortkeys[$i]["key"]));
}
}
// Use the column definition kept so far
} else {
// Turn to associative array
for ($i = 0, $coldefs = array(); $i < count($this->_coldefs); $i++) {
$coldefs[$this->_coldefs[$i]["alias"]] = $this->_coldefs[$i]["def"];
}
// Check each candidate
for ($i = 0; $i < count($this->_sortkeys); $i++) {
if (!array_key_exists($this->_sortkeys[$i]["key"], $coldefs)) {
return array("msg"=>NC_("You cannot sort by \"%s\"."),
"margs"=>array($this->_sortkeys[$i]["key"]));
}
// Reset the SQL according to the column definition
$this->_sortkeys[$i]["sql"] = $coldefs[$this->_sortkeys[$i]["key"]];
if ($this->_sortkeys[$i]["desc"]) {
$this->_sortkeys[$i]["sql"] .= " DESC";
}
}
}
// OK
return null;
}
// _compose_sortby: Compose the "sortby" argument from sorting keys
function _compose_sortby()
{
// Bounce if there is no sorting keys
if (count($this->_sortkeys) == 0) {
$this->_sortby = "";
return;
}
for ($i = 0, $sortbys = array(); $i < count($this->_sortkeys); $i++) {
if ($this->_sortkeys[$i]["desc"]) {
$sortbys[] = "-" . $this->_sortkeys[$i]["key"];
} else {
$sortbys[] = $this->_sortkeys[$i]["key"];
}
}
$this->_sortby = implode(",", $sortbys);
return;
}
// _cols: Obtain the list columns
// To be removed. Use $this->_cols instead.
function _cols()
{
// Obtain the available column list when not set yet
if (is_null($this->_cols)) {
$this->_cols = sql_cols_nl($this->_table);
}
return $this->_cols;
}
// _col_labels: Set the column labels
function _col_labels($labels)
{
$this->_col_labels = array_merge($this->_col_labels, $labels);
}
// _check_listcols: Set the columns to be displayed
function _check_listcols()
{
// The columns to be displayed
$userpref = userpref("listcols", get_class($this));
if (!is_null($userpref)) {
$listcols = explode(" ", $userpref);
} else {
$listcols = $this->_DEFAULT_LIST_COLS;
}
// Obtain the columns to list
$validcols = array_diff($this->_cols, $this->_COLS_NO_DISPLAY);
$this->_listcols = array_intersect($listcols, $validcols);
return;
}
// _query_abstract: Get the abstract regarding to the query phrase
// It always work on the "body" column
function _query_abstract($body, $html = false, $queries = null)
{
// Default to the current query phrases
if (is_null($queries)) {
$queries = $this->_query_phrases;
}
// A single query phrase is provided
if (!is_array($queries)) {
$queries = array($queries);
}
// Return nothing if body is empty
if (is_null($body)) {
return null;
}
// Strip the HTML tags
if ($html) {
$body = str_replace("<q>", "\"", $body);
$body = str_replace("</q>", "\"", $body);
$body = strip_tags($body);
$body = dh($body);
}
// Trim excess spaces
$body = preg_replace("/\s+/", " ", $body);
// Sort the query phrases by their lengths, shortest first
usort($queries, "_list_cmp_query");
// Gather the abstract of each query phrase
$bodylen = mb_strlen($body);
for ($i = 0, $ranges = array(); $i < count($queries); $i++) {
$len = mb_strlen($queries[$i]);
$base = 0;
$query = addslashes_re_php($queries[$i]);
// Gather each match
while (preg_match("/^(.*?)$query/i",
mb_substr($body, $base), $m)) {
$pos = $base + mb_strlen($m[1]);
$start = $pos - $this->_QABS_SPAN;
if ($start < 0) {
$start = 0;
}
$end = $pos + $len + $this->_QABS_SPAN;
if ($end >= $bodylen) {
$end = $bodylen - 1;
}
$ranges[] = array(
"start" => $start,
"end" => $end,
);
$base = $pos + $len;
}
}
// Sanity check
if (count($ranges) == 0) {
return null;
}
// Sort the ranges
usort($ranges, "_list_cmp_range");
// Get the union of the ranges
$union = array();
$i = 0;
$start = $ranges[0]["start"];
$end = $ranges[0]["end"];
while (true) {
// Find the next segment that exceeds the current segment
for ( ; $i < count($ranges) && $ranges[$i]["end"] <= $end; $i++) {};
// Meet the last entry
if ($i == count($ranges)) {
// Save the last segment
$union[] = array(
"start" => $start,
"end" => $end,
"len" => $end - $start,
"text" => mb_substr($body, $start, $end - $start),
);
break;
}
// A new segment seperated from the current segment
if ($ranges[$i]["start"] > $end) {
// Save the last segment
$union[] = array(
"start" => $start,
"end" => $end,
"len" => $end - $start,
"text" => mb_substr($body, $start, $end - $start),
);
// Start a new segment
$start = $ranges[$i]["start"];
$end = $ranges[$i]["end"];
continue;
}
// Expend the current segment
$end = $ranges[$i]["end"];
continue;
}
// Trim the union
$len_andsoon = 1;
$len = 0;
if ($union[0]["start"] != 0) {
$len += $len_andsoon;
}
$reached_maximum = false;
for ($i = 0; $i < count($union) - 1; $i++) {
$needlen = $union[$i]["len"] + $len_andsoon;
// Not even enough for an abstract section
if ($len + $len_andsoon > $this->_QABS_MAXLEN) {
$reached_maximum = true;
// Discard the rest sections
while (count($union) > $i) {
array_pop($union);
}
break;
// Reached the maximum
} elseif ($len + $needlen > $this->_QABS_MAXLEN) {
$reached_maximum = true;
$union[$i]["len"] = $this->_QABS_MAXLEN - $len - $len_andsoon;
$union[$i]["end"] = $union[$i]["start"] + $union[$i]["len"];
$union[$i]["text"] = mb_substr($body, $union[$i]["start"],
$union[$i]["len"]);
// Discard the rest sections
while (count($union) > $i + 1) {
array_pop($union);
}
break;
}
// Not reached the maximum yet
$len += $union[$i]["len"] + $len_andsoon;
}
// Not reached the maximum yet - check the last section
if (!$reached_maximum) {
$i = count($union) - 1;
$needlen = $union[$i]["len"];
if ($union[$i]["end"] != $bodylen) {
$needlen += $len_andsoon;
}
// Not even enough for an abstract section
if ($len + $len_andsoon > $this->_QABS_MAXLEN) {
// Forget it. We can do nothing now.
array_pop($union);
// Reached the maximum
} elseif ($len + $needlen > $this->_QABS_MAXLEN) {
$union[$i]["len"] = $this->_QABS_MAXLEN - $len - $len_andsoon;
$union[$i]["end"] = $union[$i]["start"] + $union[$i]["len"];
$union[$i]["text"] = mb_substr($body, $union[$i]["start"],
$union[$i]["len"]);
}
// Not reached the maximum yet
}
// Mark the query phrases
for ($i = 0, $union_text = array(); $i < count($union); $i++) {
$pieces = array(
array(
"text" => $union[$i]["text"],
"is_match" => false,
),
);
// Mark each query phrase
for ($j = 0; $j < count($queries); $j++) {
$query = addslashes_re_php($queries[$j]);
for ($k = 0; $k < count($pieces); $k++) {
// Skip matches of other query phrases
if ($pieces[$k]["is_match"]) {
continue;
}
// Skip if not matched
if (!preg_match("/^(.*?)($query)(.*)$/i",
$pieces[$k]["text"], $m)) {
continue;
}
$pieces = array_merge(
array_slice($pieces, 0, $k),
array(
array(
"text" => $m[1],
"is_match" => false,
),
array(
"text" => $m[2],
"is_match" => true,
),
array(
"text" => $m[3],
"is_match" => false,
),
),
array_slice($pieces, $k + 1)
);
$k++;
}
}
for ($j = 0, $text = ""; $j < count($pieces); $j++) {
if ($pieces[$j]["is_match"]) {
$text .= "<em>" . h($pieces[$j]["text"]) . "</em>";
} else {
$text .= h($pieces[$j]["text"]);
}
}
$union_text[] = $text;
}
// Join these segments
$abstract = implode("", $union_text);
if ($union[0]["start"] != 0) {
$abstract = "" . $abstract;
}
if ($union[count($union)-1]["end"] != $bodylen) {
$abstract .= "";
}
return $abstract;
}
// _html_title: Display the title
// Make it a null function
function _html_title()
{
return;
}
// _html_errmsg: Display the error message
function _html_errmsg()
{
if (is_null($this->error)) {
return;
}
$message = err2msg($this->error);
?><p class="message"><?php echo h($message); ?></p>
<?php
return;
}
// _html_lists_switch: Display the switch for different lists
function _html_lists_switch()
{
// Bounce for nothing
if (is_null($this->lists_switch) || count($this->lists_switch) == 0) {
return;
}
?><div>
<?php
for ($i = 0, $htmls = array(); $i < count($this->lists_switch); $i++) {
$htmls[] = " <a href=\"" . h($this->lists_switch[$i]["url"]) . "\">"
. h($this->lists_switch[$i]["title"]) . "</a>";
}
echo implode(" |\n", $htmls);
?></div>
<?php
return;
}
// _html_newlink: Display a link to add a new item
function _html_newlink($prompt = false)
{
// No new item creation if it is a called form
if ($this->_is_called_form) {
return;
}
if (is_null($prompt) || $prompt === false) {
return;
}
// Start from the default language
$is_ml_table = !is_null($this->_is_ml_table)? $this->_is_ml_table:
sql_is_ml_table($this->_table);
if ($is_ml_table && $this->_lang != DEFAULT_LANG) {
return;
}
$url = REQUEST_FILEQS;
// Remove list parameters
$url = rem_get_arg($url, array("query", "sortby", "pageno", "form", "formid", "statid"));
$url = add_get_arg($url, "form", "new", DUP_OK);
?><p><a href="<?php echo h($url); ?>"><?php echo h($prompt); ?></a></p>
<?php
return;
}
// _html_search: Display the search box
function _html_search($prompt = false)
{
// No search box is displayed if no records yet
if ( $this->_fetched
&& !is_null($this->total) && $this->total == 0
&& is_null($this->_query)) {
return;
}
$label = C_("Search");
?><form action="<?php echo h(REQUEST_FILE); ?>" method="get"
accept-charset="<!--monica:charset-->">
<div class="searchbox">
<?php
// Embed the list type
if (array_key_exists("list", $this->_form)) {
$type = $this->_form["list"];
?><input type="hidden" name="list" value="<?php echo h($type); ?>" />
<?php
}
// Embed the caller information
if ($this->_is_called_form) {
?><input type="hidden" name="caller" value="<?php echo h($this->_caller); ?>" />
<input type="hidden" name="cformid" value="<?php echo h($this->_cformid); ?>" />
<?php
}
if (!is_null($prompt) && $prompt !== false) {
?><label for="query"><?php echo h($prompt); ?></label>
<?php
}
$defquery = C_("(query phrase)");
$query = !is_null($this->_query) && $this->_query != ""?
$this->_query: $defquery;
?><input id="query" type="text" name="query" value="<?php echo h($query); ?>"
onfocus="if (this.value == &quot;<?php echo h($defquery); ?>&quot;) this.value = &quot;&quot;;" />
<input type="hidden" name="charset" value="<!--monica:charset-->" />
<input type="submit" value="<?php echo h($label); ?>" />
</div>
</form>
<?php
return;
}
// _html_liststat: Display the list statistics
function _html_liststat()
{
// Don't show the list
if (is_null($this->total)) {
return;
}
$message = $this->_liststat_message();
if (is_null($message)) {
return;
}
?><p><?php echo h($message); ?></p>
<?php
return;
}
// _html_pagebar: Display a page navigation bar
// We display a page bar for scrolling between previous and next 2 pages
function _html_pagebar()
{
// Don't show the list
if (is_null($this->total)) {
return;
}
// Fit in one page - paging is not needed
if ($this->_lastpage <= 1) {
return;
}
// Cache the result
static $cache;
// Cached before
if (isset($cache)) {
echo $cache;
return;
}
// Fewer than 5 pages
if ($this->_lastpage <= 5) {
$startpage = 1;
$endpage = $this->_lastpage;
// Near the beginning
} elseif ($this->_pageno < 3) {
$startpage = 1;
$endpage = 5;
// Near the end
} elseif ($this->_pageno > $this->_lastpage - 2) {
$startpage = $this->_lastpage - 4;
$endpage = $this->_lastpage;
// Normal, at the middle
} else {
$startpage = $this->_pageno - 2;
$endpage = $this->_pageno + 2;
}
// Start output
// Cache it!
ob_start();
// Static page -- Display the index
if ($this->_static) {
?><div class="pagebar">
<span><a href="."><?php echo h(C_("Index")); ?></a></span> |
<?php
// Dynamic page -- Display a paging form
} else {
// Base url without the "pageno" argument
$baseurl = rem_get_arg(REQUEST_FILEQS, "pageno");
?><form action="<?php echo h(REQUEST_FILE); ?>" method="get" accept-charset="<!--monica:charset-->">
<div class="pagebar">
<?php
if ($this->_is_called_form) {
?><input type="hidden" name="caller" value="<?php echo h($this->_caller); ?>" />
<input type="hidden" name="cformid" value="<?php echo h($this->_cformid); ?>" />
<?php
}
if (!is_null($this->_query)) {
?><input type="hidden" name="query" value="<?php echo h($this->_query); ?>" />
<?php
}
if (!is_null($this->_sortby) && $this->_sortby != "") {
?><input type="hidden" name="sortby" value="<?php echo h($this->_sortby); ?>" />
<?php
}
}
// The first page
$cell = h(C_("First"));
if ($this->_pageno != 1) {
if ($this->_static) {
$url = sprintf($this->_static_filepat, 1);
} elseif ($this->_reverse) {
$url = add_get_arg($baseurl, "pageno", 1, DUP_OK);
} else {
$url = $baseurl;
}
$cell = "<a href=\"" . h($url) . "\">" . $cell . "</a>";
}
echo " $cell |\n";
// The previous page
$cell = h(C_("Previous"));
if ($this->_pageno != 1) {
if ($this->_static) {
$url = sprintf($this->_static_filepat, $this->_pageno - 1);
} elseif ($this->_reverse || $this->_pageno - 1 != 1) {
$url = add_get_arg($baseurl, "pageno", $this->_pageno - 1, DUP_OK);
} else {
$url = $baseurl;
}
$cell = "<a href=\"" . h($url) . "\">" . $cell . "</a>";
}
echo " $cell |\n";
// Pages before
for ($i = $startpage; $i < $this->_pageno; $i++) {
$cell = h($i);
if ($this->_static) {
$url = sprintf($this->_static_filepat, $i);
} elseif ($this->_reverse || $i != 1) {
$url = add_get_arg($baseurl, "pageno", $i, DUP_OK);
} else {
$url = $baseurl;
}
$cell = "<a href=\"" . h($url) . "\">" . $cell . "</a>";
echo " $cell |\n";
}
// Current page
$cell = h($this->_pageno);
echo " $cell |\n";
// Pages after
for ($i = $this->_pageno + 1; $i <= $endpage; $i++) {
$cell = h($i);
if ($this->_static) {
if ( !is_null($this->_static_lastfile)
&& $i == $this->_lastpage) {
$url = $this->_static_lastfile;
} else {
$url = sprintf($this->_static_filepat, $i);
}
} elseif (!$this->_reverse || $i != $this->_lastpage) {
$url = add_get_arg($baseurl, "pageno", $i, DUP_OK);
} else {
$url = $baseurl;
}
$cell = "<a href=\"" . h($url) . "\">" . $cell . "</a>";
echo " $cell |\n";
}
// The next page
$cell = h(C_("Next"));
if ($this->_pageno != $this->_lastpage) {
if ($this->_static) {
if ( !is_null($this->_static_lastfile)
&& $this->_pageno + 1 == $this->_lastpage) {
$url = $this->_static_lastfile;
} else {
$url = sprintf($this->_static_filepat, $this->_pageno + 1);
}
} elseif (!$this->_reverse || $this->_pageno + 1 != $this->_lastpage) {
$url = add_get_arg($baseurl, "pageno", $this->_pageno + 1, DUP_OK);
} else {
$url = $baseurl;
}
$cell = "<a href=\"" . h($url) . "\">" . $cell . "</a>";
}
echo " $cell |\n";
// The last page
$cell = h(C_("Last"));
if ($this->_pageno != $this->_lastpage) {
if ($this->_static) {
if (!is_null($this->_static_lastfile)) {
$url = $this->_static_lastfile;
} else {
$url = sprintf($this->_static_filepat, $this->_lastpage);
}
} elseif (!$this->_reverse) {
$url = add_get_arg($baseurl, "pageno", $this->_lastpage, DUP_OK);
} else {
$url = $baseurl;
}
$cell = "<a href=\"" . h($url) . "\">" . $cell . "</a>";
}
echo " $cell\n";
if ($this->_static) {
?></div>
<?php
} else {
$submit = C_("Page:");
?> <input type="submit" value="<?php echo h($submit); ?>" />
<input type="text" name="pageno" size="5" maxlength="5" value="<?php echo h($this->_pageno); ?>" />
<input type="hidden" name="charset" value="<!--monica:charset-->" />
</div>
</form>
<?php
}
// Cache it
$cache = ob_get_contents();
ob_end_clean();
// Output the cache
echo $cache;
return;
}
// _html_list: List the items
function _html_list()
{
// Don't show the list
if (is_null($this->total)) {
return;
}
// No record to be listed
if ($this->total == 0) {
return;
}
// Remove "sortby" from the URL. first
$baseurl = REQUEST_FILEQS;
$baseurl = rem_get_arg($baseurl, array("formid", "statid", "sortby", "pageno"));
// Check the URL. first
if (in_array("_urlcheck", $this->_listcols)) {
urlcheck($this->_current);
}
// Mass deletion -- surround it with a form
if ($this->_massdel && !$this->_is_called_form) {
$massdel = C_("Delete the selected items.");
?><form action="<?php echo h(REQUEST_FILE); ?>" method="post">
<div><input type="hidden" name="form" value="_massdel" /><input
type="hidden" name="referer2" value="<?php echo h(REQUEST_FULLURI); ?>" /><input
type="submit" value="<?php echo h($massdel); ?>" /></div>
<?php
}
?><table class="deflist">
<colgroup><?php
if (!$this->_nonumber) {
echo "<col />";
}
if ($this->_massdel && !$this->_is_called_form) {
echo "<col />";
}
if (in_array("_viewurl", $this->_cols) && !$this->_is_called_form) {
echo "<col />";
}
if (!$this->_noselect) {
echo "<col />";
}
for ($i = 0; $i < count($this->_listcols); $i++) {
echo "<col />";
}
?></colgroup>
<thead>
<tr>
<?php
if (!$this->_nonumber) {
?> <th class="listno" scope="col"><?php echo h_abbr(C_("No.")); ?></th>
<?php
}
if ($this->_massdel && !$this->_is_called_form) {
?> <th class="listdel" scope="col"><?php echo h_abbr(C_("Delete")); ?></th>
<?php
}
if (in_array("_viewurl", $this->_cols) && !$this->_is_called_form) {
?> <th scope="col"><?php echo h_abbr(C_("View")); ?></th>
<?php
}
if (!$this->_noselect) {
?> <th scope="col"><?php echo h_abbr($this->_seltext); ?></th>
<?php
}
foreach ($this->_listcols as $col) {
$label = array_key_exists($col, $this->_col_labels)?
$this->_col_labels[$col]: $col;
if ($this->_nosortby || in_array($col, $this->_COLS_NO_SORT_BY)) {
?> <th scope="col"><?php echo h_abbr($label); ?></th>
<?php
} else {
$url = add_get_arg($baseurl, "sortby",
(($this->_sortby == $col)? "-" . $col: $col), DUP_OK);
?> <th scope="col"><a href="<?php echo h($url); ?>"><?php echo h_abbr($label); ?></a></th>
<?php
}
}
?></tr>
</thead>
<tbody>
<?php
// Print each record
for ($i = 0; $i < count($this->_current); $i++) {
$no = $this->_startno + $i + 1;
$rowclass = ($i % 2 == 0)? "evenrow": "oddrow";
$current =& $this->_current[$i];
$issel = ((!in_array("_sel", $this->_cols) || $current["_sel"])
&& !$this->_noselect);
// The URL. to handle the selection
if ($issel) {
if ( array_key_exists("_selurl", $current)
&& !$this->_is_called_form) {
$selurl = $current["_selurl"];
} else {
$selurl = sprintf($this->_selurl_tmpl, $current["sn"]);
}
}
?><tr class="<?php echo h($rowclass); ?>">
<?php
if (!$this->_nonumber) {
?> <td class="listno"><?php echo h($no); ?></td>
<?php
}
if ($this->_massdel && !$this->_is_called_form) {
$name = "delsn" . $current["sn"];
?> <td class="listdel"><input type="checkbox" name="<?php echo h($name); ?>" /></td>
<?php
}
if (in_array("_viewurl", $this->_cols) && !$this->_is_called_form) {
if (is_null($current["_viewurl"])) {
?> <td></td>
<?php
} else {
$viewurl = $current["_viewurl"];
?> <td><a href="<?php echo h($viewurl); ?>"><?php
echo h(C_("View")); ?></a></td>
<?php
}
}
if (!$this->_noselect) {
?> <td><?php
if ($issel) {
?><a href="<?php echo h($selurl); ?>"><?php
echo h($this->_seltext); ?></a><?php
}
?></td>
<?php
}
foreach ($this->_listcols as $col) {
?> <td><?php $this->_echo_colval($col, $current); ?></td>
<?php
}
?></tr>
<?php
}
?></tbody>
</table>
<?php
// Mass deletion -- surround it with a form
if ($this->_massdel && !$this->_is_called_form) {
$massdel = C_("Delete the selected items.");
?><div><input type="submit" value="<?php echo h($massdel); ?>" /></div>
</form>
<?php
}
return;
}
// _html_list_th: Display the table header cell of the list
function _html_list_th($baseurl, $col)
{
$label = array_key_exists($col, $this->_col_labels)?
$this->_col_labels[$col]: $col;
if ($this->_nosortby || in_array($col, $this->_COLS_NO_SORT_BY)) {
?> <th scope="col"><?php echo h_abbr($label); ?></th>
<?php
} else {
$url = add_get_arg($baseurl, "sortby",
(($this->_sortby == $col)? "-" . $col: $col), DUP_OK);
?> <th scope="col"><a href="<?php echo h($url); ?>"><?php echo h_abbr($label); ?></a></th>
<?php
}
}
// _html_listprefform: Display a form to change the list preference
function _html_listprefform()
{
// Don't show the list
if (is_null($this->total)) {
return;
}
// No record to be listed
if ($this->total == 0) {
return;
}
// Return if users preferences are not available
if (!use_users() || !isset($_SESSION) || is_null(get_login_sn())) {
return;
}
$submit = C_("Set");
// The referer
$referer = rem_get_arg(REQUEST_FULLURI, "statid");
// Obtain the columns to list
$validcols = array_diff($this->_cols, $this->_COLS_NO_DISPLAY);
?><form class="listprefform" action="<?php echo h(REQUEST_FILE); ?>" method="post"
accept-charset="<!--monica:charset-->">
<p><input type="hidden" name="charset" value="<!--monica:charset-->" />
<input type="hidden" name="form" value="listpref" />
<input type="hidden" name="referer" value="<?php echo h($referer); ?>" />
<input type="hidden" name="domain" value="<?php echo h(get_class($this)); ?>" />
<?php
// The number of rows per page
?><label for="listsize"><?php echo h(C_("Rows per page:")); ?></label><input
id="listsize" type="text" name="listsize" size="5" maxlength="5" value="<?php echo h($this->_pagesize); ?>" />
<?php
// The display columns
echo h(C_("Display columns:")) . "\n";
foreach ($validcols as $col) {
$label = array_key_exists($col, $this->_col_labels)? $this->_col_labels[$col]:
$col;
$name = "listcols_" . $col;
?><span><input id="<?php echo h($name); ?>" type="checkbox" name="<?php echo h($name); ?>"<?php
if (in_array($col, $this->_listcols)) {
echo " checked=\"checked\"";
}
?> /><label for="<?php echo h($name); ?>"><?php echo h_abbr($label); ?></label></span>
<?php
}
?><input type="submit" name="confirm" value="<?php echo h($submit); ?>" /></p>
</form>
<?php
return;
}
}
// UsersList: Users list handler class
class UsersList extends BaseList
{
// __construct: Initialize the handler
function __construct($FORM = null, $table = "users")
{
parent::__construct($FORM, $table);
// The page title
$this->title = $this->_is_called_form? C_("Select a User"):
C_("Manage Users");
// The default sort order
$this->_DEFAULT_SORTBY = "id";
// Column labels
$this->_col_labels(array(
"id" => C_("User ID."),
"name" => C_("Full name"),
"deleted" => C_("Deleted?"),
"lang" => C_("Pref. language"),
"visits" => C_("Visits"),
"visited" => C_("Visited"),
"ip" => C_("IP"),
"host" => C_("Host"),
"ct" => C_("From country"),
"fails" => C_("Fail logins"),
));
}
// _sql_cols: Obtain the SQL columns list phase
function _sql_cols()
{
// Adjust the column list
$this->_cols = array_values(array_diff($this->_cols,
array("passwd")));
// Run the parent method
return parent::_sql_cols();
}
// _coldef: Column definition for non-view usage
function _coldef($col)
{
// Obtain the column definition
switch ($col) {
case "lang":
$cases = array();
foreach (array_keys($GLOBALS["LNINFO"]) as $lang) {
$cases[] = "WHEN '" . sql_esctext($lang) . "'"
. " THEN '" . sql_esctext(ln($lang, LN_DESC_CURLC)) . "'";
}
return "CASE " . $this->_table . "." . $col . " "
. implode(" ", $cases) . " END";
case "disabled":
return "CASE WHEN " . sql_is_true($this->_table . "." . $col)
. " THEN '" . sql_esctext(C_("Disabled")) . "'"
. " ELSE '' END";
case "deleted":
return "CASE WHEN " . sql_is_true($this->_table . "." . $col)
. " THEN '" . sql_esctext(C_("Deleted")) . "'"
. " ELSE '' END";
default:
return parent::_coldef($col);
}
}
// _html_newlink: Display a link to add a new item
function _html_newlink($prompt = false)
{
if ($prompt === false) {
$prompt = C_("Add a new user account.");
}
// Run the parent method
return parent::_html_newlink($prompt);
}
// _html_search: Display the search box
function _html_search($prompt = false)
{
if ($prompt === false) {
$prompt = C_("Search for a user:");
}
// Run the parent method
return parent::_html_search($prompt);
}
// _liststat_message: Return the current list statistics message
function _liststat_message()
{
// No record to list
if ($this->total == 0) {
// Inherit the empty list statistics message
return parent::_liststat_message();
// Fit in one page
} elseif ($this->_pagesize === false || $this->total <= $this->_pagesize) {
// Result comes from a query
if (!is_null($this->_query)) {
return sprintf(dngettext(COMMONDOMAIN,
"Your query found %s user.",
"Your query found %s users.",
$this->total),
number_format($this->total));
// List result
} else {
return sprintf(dngettext(COMMONDOMAIN,
"%s user.",
"%s users.",
$this->total),
number_format($this->total));
}
// More than one page
} else {
if (!is_null($this->_query)) {
return sprintf(dngettext(COMMONDOMAIN,
"Your query found %s user, listing %s to %s.",
"Your query found %s users, listing %s to %s.",
$this->total),
number_format($this->total),
number_format($this->_startno+1),
number_format($this->_endno+1));
// List result
} else {
return sprintf(dngettext(COMMONDOMAIN,
"%s user, listing %s to %s.",
"%s users, listing %s to %s.",
$this->total),
number_format($this->total),
number_format($this->_startno+1),
number_format($this->_endno+1));
}
}
}
}
// GroupsList: Groups list handler class
class GroupsList extends BaseList
{
// __construct: Initialize the handler
function __construct($FORM = null, $table = "groups")
{
parent::__construct($FORM, $table);
// The page title
$this->title = $this->_is_called_form? C_("Select a Group"):
C_("Manage Groups");
// The default sort order
$this->_DEFAULT_SORTBY = "id";
// Column labels
$this->_col_labels(array(
"id" => C_("Group ID."),
));
}
// _html_newlink: Display a link to add a new item
function _html_newlink($prompt = false)
{
if ($prompt === false) {
$prompt = C_("Add a new group.");
}
// Run the parent method
return parent::_html_newlink($prompt);
}
// _html_search: Display the search box
function _html_search($prompt = false)
{
if ($prompt === false) {
$prompt = C_("Search for a group:");
}
// Run the parent method
return parent::_html_search($prompt);
}
// _liststat_message: Return the current list statistics message
function _liststat_message()
{
// No record to list
if ($this->total == 0) {
// Inherit the empty list statistics message
return parent::_liststat_message();
// Fit in one page
} elseif ($this->_pagesize === false || $this->total <= $this->_pagesize) {
// Result comes from a query
if (!is_null($this->_query)) {
return sprintf(dngettext(COMMONDOMAIN,
"Your query found %s group.",
"Your query found %s groups.",
$this->total),
number_format($this->total));
// List result
} else {
return sprintf(dngettext(COMMONDOMAIN,
"%s group.",
"%s groups.",
$this->total),
number_format($this->total));
}
// More than one page
} else {
if (!is_null($this->_query)) {
return sprintf(dngettext(COMMONDOMAIN,
"Your query found %s group, listing %s to %s.",
"Your query found %s groups, listing %s to %s.",
$this->total),
number_format($this->total),
number_format($this->_startno+1),
number_format($this->_endno+1));
// List result
} else {
return sprintf(dngettext(COMMONDOMAIN,
"%s group, listing %s to %s.",
"%s groups, listing %s to %s.",
$this->total),
number_format($this->total),
number_format($this->_startno+1),
number_format($this->_endno+1));
}
}
}
}
// UserMembershipsList: User memberships list handler class
class UserMembershipsList extends BaseList
{
// __construct: Initialize the handler
function __construct($FORM = null, $table = "usermem")
{
parent::__construct($FORM, $table);
// The page title
$this->title = $this->_is_called_form?
C_("Select a User Membership Record"):
C_("Manage User Membership");
// The default sort order
$this->_DEFAULT_SORTBY = "grp,member";
// Column labels
$this->_col_labels(array(
"grp" => C_("Group"),
"member" => C_("Member"),
));
}
// _coldef: Column definition for non-view usage
function _coldef($col)
{
// Obtain the column definition
switch ($col) {
case "grp":
// Default language
if ($this->_lang == DEFAULT_LANG) {
return sql_strcat("groups.id", "' ('",
"groups.dsc_" . ln($this->_lang, LN_DATABASE), "')'");
// Fall back to the default language
} else {
$thiscol = "groups.dsc_"
. ln($this->_lang, LN_DATABASE);
$defcol = "groups.dsc_"
. ln(DEFAULT_LANG, LN_DATABASE);
return sql_strcat("groups.id", "' ('",
"COALESCE($thiscol, $defcol)", "')'");
}
case "member":
return sql_strcat("usrmembers.id", "' ('", "usrmembers.name", "')'");
default:
return parent::_coldef($col);
}
}
// _sql_join: Get the SQL JOIN phase
function _sql_join()
{
$join = "";
$join .= " LEFT JOIN groups ON " . $this->_table . ".grp=groups.sn";
$join .= " LEFT JOIN users AS usrmembers ON " . $this->_table . ".member=usrmembers.sn";
return $join . parent::_sql_join();
}
// _html_newlink: Display a link to add a new item
function _html_newlink($prompt = false)
{
if ($prompt === false) {
$prompt = C_("Add a new membership record.");
}
// Run the parent method
return parent::_html_newlink($prompt);
}
// _html_search: Display the search box
function _html_search($prompt = false)
{
if ($prompt === false) {
$prompt = C_("Search for a membership record:");
}
// Run the parent method
return parent::_html_search($prompt);
}
// _liststat_message: Return the current list statistics message
function _liststat_message()
{
// No record to list
if ($this->total == 0) {
// Inherit the empty list statistics message
return parent::_liststat_message();
// Fit in one page
} elseif ($this->_pagesize === false || $this->total <= $this->_pagesize) {
// Result comes from a query
if (!is_null($this->_query)) {
return sprintf(dngettext(COMMONDOMAIN,
"Your query found %s membership record.",
"Your query found %s membership records.",
$this->total),
number_format($this->total));
// List result
} else {
return sprintf(dngettext(COMMONDOMAIN,
"%s membership record.",
"%s membership records.",
$this->total),
number_format($this->total));
}
// More than one page
} else {
if (!is_null($this->_query)) {
return sprintf(dngettext(COMMONDOMAIN,
"Your query found %s membership record, listing %s to %s.",
"Your query found %s membership records, listing %s to %s.",
$this->total),
number_format($this->total),
number_format($this->_startno+1),
number_format($this->_endno+1));
// List result
} else {
return sprintf(dngettext(COMMONDOMAIN,
"%s membership record, listing %s to %s.",
"%s membership records, listing %s to %s.",
$this->total),
number_format($this->total),
number_format($this->_startno+1),
number_format($this->_endno+1));
}
}
}
}
// GroupMembershipsList: Group memberships list handler class
class GroupMembershipsList extends BaseList
{
// __construct: Initialize the handler
function __construct($FORM = null, $table = "groupmem")
{
parent::__construct($FORM, $table);
// The page title
$this->title = $this->_is_called_form?
C_("Select a Group Membership Record"):
C_("Manage Group Membership");
// The default sort order
$this->_DEFAULT_SORTBY = "grp,member";
// Column labels
$this->_col_labels(array(
"grp" => C_("Group"),
"member" => C_("Member"),
));
}
// _coldef: Column definition for non-view usage
function _coldef($col)
{
// Obtain the column definition
switch ($col) {
case "grp":
// Default language
if ($this->_lang == DEFAULT_LANG) {
return sql_strcat("groups.id", "' ('",
"groups.dsc_" . ln($this->_lang, LN_DATABASE), "')'");
// Fall back to the default language
} else {
$thiscol = "groups.dsc_" . ln($this->_lang, LN_DATABASE);
$defcol = "groups.dsc_" . ln(DEFAULT_LANG, LN_DATABASE);
return sql_strcat("groups.id", "' ('",
"COALESCE($thiscol, $defcol)", "')'");
}
case "member":
// Default language
if ($this->_lang == DEFAULT_LANG) {
return sql_strcat("grpmembers.id", "' ('",
"grpmembers.dsc_" . ln($this->_lang, LN_DATABASE), "')'");
// Fall back to the default language
} else {
$thiscol = "grpmembers.dsc_" . ln($this->_lang, LN_DATABASE);
$defcol = "grpmembers.dsc_" . ln(DEFAULT_LANG, LN_DATABASE);
return sql_strcat("grpmembers.id", "' ('",
"COALESCE($thiscol, $defcol)", "')'");
}
default:
return parent::_coldef($col);
}
}
// _sql_join: Get the SQL JOIN phase
function _sql_join()
{
$join = "";
$join .= " LEFT JOIN groups ON " . $this->_table . ".grp=groups.sn";
$join .= " LEFT JOIN groups AS grpmembers ON " . $this->_table . ".member=grpmembers.sn";
return $join . parent::_sql_join();
}
// _html_newlink: Display a link to add a new item
function _html_newlink($prompt = false)
{
if ($prompt === false) {
$prompt = C_("Add a new membership record.");
}
// Run the parent method
return parent::_html_newlink($prompt);
}
// _html_search: Display the search box
function _html_search($prompt = false)
{
if ($prompt === false) {
$prompt = C_("Search for a membership record:");
}
// Run the parent method
return parent::_html_search($prompt);
}
// _liststat_message: Return the current list statistics message
function _liststat_message()
{
// No record to list
if ($this->total == 0) {
// Inherit the empty list statistics message
return parent::_liststat_message();
// Fit in one page
} elseif ($this->_pagesize === false || $this->total <= $this->_pagesize) {
// Result comes from a query
if (!is_null($this->_query)) {
return sprintf(dngettext(COMMONDOMAIN,
"Your query found %s membership record.",
"Your query found %s membership records.",
$this->total),
number_format($this->total));
// List result
} else {
return sprintf(dngettext(COMMONDOMAIN,
"%s membership record.",
"%s membership records.",
$this->total),
number_format($this->total));
}
// More than one page
} else {
if (!is_null($this->_query)) {
return sprintf(dngettext(COMMONDOMAIN,
"Your query found %s membership record, listing %s to %s.",
"Your query found %s membership records, listing %s to %s.",
$this->total),
number_format($this->total),
number_format($this->_startno+1),
number_format($this->_endno+1));
// List result
} else {
return sprintf(dngettext(COMMONDOMAIN,
"%s membership record, listing %s to %s.",
"%s membership records, listing %s to %s.",
$this->total),
number_format($this->total),
number_format($this->_startno+1),
number_format($this->_endno+1));
}
}
}
}
// ScriptPrivilegesList: Script privileges list handler class
class ScriptPrivilegesList extends BaseList
{
// __construct: Initialize the handler
function __construct($FORM = null, $table = "scptpriv")
{
parent::__construct($FORM, $table);
// The page title
$this->title = $this->_is_called_form?
C_("Select a Script Privilege Record"):
C_("Manage Script Privileges");
// The default sort order
$this->_DEFAULT_SORTBY = "script,grp";
// Column labels
$this->_col_labels(array(
"script" => C_("Script"),
"grp" => C_("Privilege"),
));
}
// _coldef: Column definition for non-view usage
function _coldef($col)
{
// Obtain the column definition
switch ($col) {
case "grp":
// Default language
if ($this->_lang == DEFAULT_LANG) {
return sql_strcat("groups.id", "' ('",
"groups.dsc_" . ln($this->_lang, LN_DATABASE), "')'");
// Fall back to the default language
} else {
$thiscol = "groups.dsc_" . ln($this->_lang, LN_DATABASE);
$defcol = "groups.dsc_" . ln(DEFAULT_LANG, LN_DATABASE);
return sql_strcat("groups.id", "' ('",
"COALESCE($thiscol, $defcol)", "')'");
}
default:
return parent::_coldef($col);
}
}
// _sql_join: Get the SQL JOIN phase
function _sql_join()
{
$join = "";
$join .= " LEFT JOIN groups ON " . $this->_table . ".grp=groups.sn";
return $join . parent::_sql_join();
}
// _html_newlink: Display a link to add a new item
function _html_newlink($prompt = false)
{
if ($prompt === false) {
$prompt = C_("Add a new script privilege record.");
}
// Run the parent method
return parent::_html_newlink($prompt);
}
// _html_search: Display the search box
function _html_search($prompt = false)
{
if ($prompt === false) {
$prompt = C_("Search for a script privilege record:");
}
// Run the parent method
return parent::_html_search($prompt);
}
// _liststat_message: Return the current list statistics message
function _liststat_message()
{
// No record to list
if ($this->total == 0) {
// Inherit the empty list statistics message
return parent::_liststat_message();
// Fit in one page
} elseif ($this->_pagesize === false || $this->total <= $this->_pagesize) {
// Result comes from a query
if (!is_null($this->_query)) {
return sprintf(dngettext(COMMONDOMAIN,
"Your query found %s script privilege record.",
"Your query found %s script privilege records.",
$this->total),
number_format($this->total));
// List result
} else {
return sprintf(dngettext(COMMONDOMAIN,
"%s script privilege record.",
"%s script privilege records.",
$this->total),
number_format($this->total));
}
// More than one page
} else {
if (!is_null($this->_query)) {
return sprintf(dngettext(COMMONDOMAIN,
"Your query found %s script privilege record, listing %s to %s.",
"Your query found %s script privilege records, listing %s to %s.",
$this->total),
number_format($this->total),
number_format($this->_startno+1),
number_format($this->_endno+1));
// List result
} else {
return sprintf(dngettext(COMMONDOMAIN,
"%s script privilege record, listing %s to %s.",
"%s script privilege records, listing %s to %s.",
$this->total),
number_format($this->total),
number_format($this->_startno+1),
number_format($this->_endno+1));
}
}
}
}
// UserPreferencesList: User preferences list handler class
class UserPreferencesList extends BaseList
{
// __construct: Initialize the handler
function __construct($FORM = null, $table = "userpref")
{
parent::__construct($FORM, $table);
// The page title
$this->title = $this->_is_called_form?
C_("Select a User Preference"):
C_("Manage User Preferences");
// The default sort order
$this->_DEFAULT_SORTBY = "domain,usr,name";
// Columns that should display its brief instead
$this->_COLS_BRIEF = array("value");
// Column labels
$this->_col_labels(array(
"usr" => C_("User"),
"domain" => C_("Domain"),
"value" => C_("Value"),
));
}
// _coldef: Column definition for non-view usage
function _coldef($col)
{
// Obtain the column definition
switch ($col) {
case "usr":
return "CASE WHEN " . $this->_table . ".usr IS NOT NULL"
. " THEN users.name"
. " ELSE '" . sql_esctext(C_("Everyone")) . "' END";
case "domain":
return "CASE WHEN " . $this->_table . ".domain IS NOT NULL"
. " THEN " . $this->_table . ".domain"
. " ELSE '" . sql_esctext(C_("Everywhere")) . "' END";
default:
return parent::_coldef($col);
}
}
// _sql_join: Get the SQL JOIN phase
function _sql_join()
{
$join = "";
$join = " LEFT JOIN users ON " . $this->_table . ".usr=users.sn";
return $join . parent::_sql_join();
}
// _html_newlink: Display a link to add a new item
function _html_newlink($prompt = false)
{
if ($prompt === false) {
$prompt = C_("Add a new user preference.");
}
// Run the parent method
return parent::_html_newlink($prompt);
}
// _html_search: Display the search box
function _html_search($prompt = false)
{
if ($prompt === false) {
$prompt = C_("Search for a user preference:");
}
// Run the parent method
return parent::_html_search($prompt);
}
// _liststat_message: Return the current list statistics message
function _liststat_message()
{
// No record to list
if ($this->total == 0) {
// Inherit the empty list statistics message
return parent::_liststat_message();
// Fit in one page
} elseif ($this->_pagesize === false || $this->total <= $this->_pagesize) {
// Result comes from a query
if (!is_null($this->_query)) {
return sprintf(dngettext(COMMONDOMAIN,
"Your query found %s user preference.",
"Your query found %s user preferences.",
$this->total),
number_format($this->total));
// List result
} else {
return sprintf(dngettext(COMMONDOMAIN,
"%s user preference.",
"%s user preferences.",
$this->total),
number_format($this->total));
}
// More than one page
} else {
if (!is_null($this->_query)) {
return sprintf(dngettext(COMMONDOMAIN,
"Your query found %s user preference, listing %s to %s.",
"Your query found %s user preferences, listing %s to %s.",
$this->total),
number_format($this->total),
number_format($this->_startno+1),
number_format($this->_endno+1));
// List result
} else {
return sprintf(dngettext(COMMONDOMAIN,
"%s user preference, listing %s to %s.",
"%s user preferences, listing %s to %s.",
$this->total),
number_format($this->total),
number_format($this->_startno+1),
number_format($this->_endno+1));
}
}
}
}
// UserRequestsList: User requests list handler class
class UserRequestsList extends BaseList
{
// __construct: Initialize the handler
function __construct($FORM = null, $table = "userreq")
{
parent::__construct($FORM, $table);
// The page title
$this->title = $this->_is_called_form? C_("Select a User Request"):
C_("Manage User Requests");
// Columns that should display its brief instead
$this->_COLS_BRIEF = array("args");
// Column labels
$this->_col_labels(array(
"type" => C_("Type"),
"usr" => C_("User"),
"args" => C_("Arguments"),
"expire" => C_("Expiration"),
));
}
// _html_newlink: Display a link to add a new item
function _html_newlink($prompt = false)
{
if ($prompt === false) {
$prompt = C_("Add a new user request.");
}
// Run the parent method
return parent::_html_newlink($prompt);
}
// _html_search: Display the search box
function _html_search($prompt = false)
{
if ($prompt === false) {
$prompt = C_("Search for a user request:");
}
// Run the parent method
return parent::_html_search($prompt);
}
// _liststat_message: Return the current list statistics message
function _liststat_message()
{
// No record to list
if ($this->total == 0) {
// Inherit the empty list statistics message
return parent::_liststat_message();
// Fit in one page
} elseif ($this->_pagesize === false || $this->total <= $this->_pagesize) {
// Result comes from a query
if (!is_null($this->_query) && $this->_query != "") {
return sprintf(dngettext(COMMONDOMAIN,
"Your query found %s user request.",
"Your query found %s user requests.",
$this->total),
number_format($this->total));
// List result
} else {
return sprintf(dngettext(COMMONDOMAIN,
"%s user request.",
"%s user requests.",
$this->total),
number_format($this->total));
}
// More than one page
} else {
if (!is_null($this->_query) && $this->_query != "") {
return sprintf(dngettext(COMMONDOMAIN,
"Your query found %s user request, listing %s to %s.",
"Your query found %s user requests, listing %s to %s.",
$this->total),
number_format($this->total),
number_format($this->_startno+1),
number_format($this->_endno+1));
// List result
} else {
return sprintf(dngettext(COMMONDOMAIN,
"%s user request, listing %s to %s.",
"%s user requests, listing %s to %s.",
$this->total),
number_format($this->total),
number_format($this->_startno+1),
number_format($this->_endno+1));
}
}
}
}
// BaseCategoriesList: Base categories list handler class
class BaseCategoriesList extends BaseList
{
// __construct: Initialize the handler
function __construct($FORM = null, $table = null)
{
parent::__construct($FORM, $table);
// The default sort order
$this->_DEFAULT_SORTBY = "ord,id";
}
// _html_newlink: Display a link to add a new item
function _html_newlink($prompt = false)
{
if ($prompt === false) {
$prompt = C_("Add a new category.");
}
// Run the parent method
return parent::_html_newlink($prompt);
}
// _html_search: Display the search box
function _html_search($prompt = false)
{
if ($prompt === false) {
$prompt = C_("Search for a category:");
}
// Run the parent method
return parent::_html_search($prompt);
}
// _liststat_message: Return the current list statistics message
function _liststat_message()
{
// No record to list
if ($this->total == 0) {
// Inherit the empty list statistics message
return parent::_liststat_message();
// Fit in one page
} elseif ($this->_pagesize === false || $this->total <= $this->_pagesize) {
// Result comes from a query
if (!is_null($this->_query) && $this->_query != "") {
return sprintf(dngettext(COMMONDOMAIN,
"Your query found %s category.",
"Your query found %s categories.",
$this->total),
number_format($this->total));
// List result
} else {
return sprintf(dngettext(COMMONDOMAIN,
"%s category.",
"%s categories.",
$this->total),
number_format($this->total));
}
// More than one page
} else {
if (!is_null($this->_query) && $this->_query != "") {
return sprintf(dngettext(COMMONDOMAIN,
"Your query found %s category, listing %s to %s.",
"Your query found %s categories, listing %s to %s.",
$this->total),
number_format($this->total),
number_format($this->_startno+1),
number_format($this->_endno+1));
// List result
} else {
return sprintf(dngettext(COMMONDOMAIN,
"%s category, listing %s to %s.",
"%s categories, listing %s to %s.",
$this->total),
number_format($this->total),
number_format($this->_startno+1),
number_format($this->_endno+1));
}
}
}
}
// BaseCategorizationList: Base categorization records list handler class
class BaseCategorizationList extends BaseList
{
// _html_newlink: Display a link to add a new item
function _html_newlink($prompt = false)
{
if ($prompt === false) {
$prompt = C_("Add a new categorization record.");
}
// Run the parent method
return parent::_html_newlink($prompt);
}
// _html_search: Display the search box
function _html_search($prompt = false)
{
if ($prompt === false) {
$prompt = C_("Search for a categorization record:");
}
// Run the parent method
return parent::_html_search($prompt);
}
// _liststat_message: Return the current list statistics message
function _liststat_message()
{
// No record to list
if ($this->total == 0) {
// Inherit the empty list statistics message
return parent::_liststat_message();
// Fit in one page
} elseif ($this->_pagesize === false || $this->total <= $this->_pagesize) {
// Result comes from a query
if (!is_null($this->_query) && $this->_query != "") {
return sprintf(dngettext(COMMONDOMAIN,
"Your query found %s categorization record.",
"Your query found %s categorization records.",
$this->total),
number_format($this->total));
// List result
} else {
return sprintf(dngettext(COMMONDOMAIN,
"%s categorization record.",
"%s categorization records.",
$this->total),
number_format($this->total));
}
// More than one page
} else {
if (!is_null($this->_query) && $this->_query != "") {
return sprintf(dngettext(COMMONDOMAIN,
"Your query found %s categorization record, listing %s to %s.",
"Your query found %s categorization records, listing %s to %s.",
$this->total),
number_format($this->total),
number_format($this->_startno+1),
number_format($this->_endno+1));
// List result
} else {
return sprintf(dngettext(COMMONDOMAIN,
"%s categorization record, listing %s to %s.",
"%s categorization records, listing %s to %s.",
$this->total),
number_format($this->total),
number_format($this->_startno+1),
number_format($this->_endno+1));
}
}
}
}
// PagesList: Pages list handler class
class PagesList extends BaseList
{
// __construct: Initialize the handler
function __construct($FORM = null, $table = "pages")
{
parent::__construct($FORM, $table);
// The page title
$this->title = $this->_is_called_form? C_("Select a Page"):
C_("Manage Pages");
// The default sort order
$this->_DEFAULT_SORTBY = "path";
// Columns that should display its brief instead
$this->_COLS_BRIEF = array("body");
}
// _sql_cols: Obtain the SQL columns list phase
function _sql_cols()
{
// Adjust the column list
$this->_cols = array_merge(array("_viewurl"), $this->_cols);
// Run the parent method
return parent::_sql_cols();
}
// _coldef: Column definition for non-view usage
function _coldef($col)
{
// Obtain the column definition
switch ($col) {
case "_viewurl":
return sql_strcat( "'/" . ln($this->_lang, LN_FILENAME) . "'",
$this->_table . ".path");
case "html":
return "CASE WHEN " . sql_is_true($this->_table . "." . $col)
. " THEN '" . sql_esctext(C_("HTML")) . "'"
. " ELSE '" . sql_esctext(C_("Plain text")) . "' END";
case "hid":
return "CASE WHEN " . sql_is_true($this->_table . "." . $col)
. " THEN '" . sql_esctext(C_("Hidden")) . "'"
. " ELSE '" . sql_esctext(C_("Shown")) . "' END";
default:
return parent::_coldef($col);
}
}
// _html_newlink: Display a link to add a new item
function _html_newlink($prompt = false)
{
if ($prompt === false) {
$prompt = C_("Write a new page.");
}
// Run the parent method
return parent::_html_newlink($prompt);
}
// _html_search: Display the search box
function _html_search($prompt = false)
{
if ($prompt === false) {
$prompt = C_("Search for a page:");
}
// Run the parent method
return parent::_html_search($prompt);
}
// _liststat_message: Return the current list statistics message
function _liststat_message()
{
// No record to list
if ($this->total == 0) {
// Inherit the empty list statistics message
return parent::_liststat_message();
// Fit in one page
} elseif ($this->_pagesize === false || $this->total <= $this->_pagesize) {
// Result comes from a query
if (!is_null($this->_query)) {
return sprintf(dngettext(COMMONDOMAIN,
"Your query found %s page.",
"Your query found %s pages.",
$this->total),
number_format($this->total));
// List result
} else {
return sprintf(dngettext(COMMONDOMAIN,
"%s page.",
"%s pages.",
$this->total),
number_format($this->total));
}
// More than one page
} else {
if (!is_null($this->_query)) {
return sprintf(dngettext(COMMONDOMAIN,
"Your query found %s page, listing %s to %s.",
"Your query found %s pages, listing %s to %s.",
$this->total),
number_format($this->total),
number_format($this->_startno+1),
number_format($this->_endno+1));
// List result
} else {
return sprintf(dngettext(COMMONDOMAIN,
"%s page, listing %s to %s.",
"%s pages, listing %s to %s.",
$this->total),
number_format($this->total),
number_format($this->_startno+1),
number_format($this->_endno+1));
}
}
}
}
// NewsList: News list handler class
class NewsList extends BaseList
{
// __construct: Initialize the handler
function __construct($FORM = null, $table = "news")
{
parent::__construct($FORM, $table);
// The page title
$this->title = $this->_is_called_form? C_("Select a News Article"):
C_("Manage News");
// The default sort order
$this->_DEFAULT_SORTBY = "-date,-ord";
// Columns that should display its brief instead
$this->_COLS_BRIEF = array("body");
}
// _sql_cols: Obtain the SQL columns list phase
function _sql_cols()
{
// Adjust the column list
$this->_cols = array_merge(array("_viewurl"), $this->_cols);
// Run the parent method
return parent::_sql_cols();
}
// _coldef: Column definition for non-view usage
function _coldef($col)
{
// Obtain the column definition
switch ($col) {
case "_viewurl":
return sql_strcat( "'/" . ln($this->_lang, LN_FILENAME) . "/news'",
$this->_table . ".date");
case "html":
return "CASE WHEN " . sql_is_true($this->_table . "." . $col)
. " THEN '" . sql_esctext(C_("HTML")) . "'"
. " ELSE '" . sql_esctext(C_("Plain text")) . "' END";
case "hid":
return "CASE WHEN " . sql_is_true($this->_table . "." . $col)
. " THEN '" . sql_esctext(C_("Hidden")) . "'"
. " ELSE '" . sql_esctext(C_("Shown")) . "' END";
default:
return parent::_coldef($col);
}
}
// _html_newlink: Display a link to add a new item
function _html_newlink($prompt = false)
{
if ($prompt === false) {
$prompt = C_("Write a new news article.");
}
// Run the parent method
return parent::_html_newlink($prompt);
}
// _html_search: Display the search box
function _html_search($prompt = false)
{
if ($prompt === false) {
$prompt = C_("Search for a news article:");
}
// Run the parent method
return parent::_html_search($prompt);
}
// _liststat_message: Return the current list statistics message
function _liststat_message()
{
// No record to list
if ($this->total == 0) {
// Inherit the empty list statistics message
return parent::_liststat_message();
// Fit in one page
} elseif ($this->_pagesize === false || $this->total <= $this->_pagesize) {
// Result comes from a query
if (!is_null($this->_query)) {
return sprintf(dngettext(COMMONDOMAIN,
"Your query found %s news article.",
"Your query found %s news articles.",
$this->total),
number_format($this->total));
// List result
} else {
return sprintf(dngettext(COMMONDOMAIN,
"%s news article.",
"%s news articles.",
$this->total),
number_format($this->total));
}
// More than one page
} else {
if (!is_null($this->_query)) {
return sprintf(dngettext(COMMONDOMAIN,
"Your query found %s news article, listing %s to %s.",
"Your query found %s news articles, listing %s to %s.",
$this->total),
number_format($this->total),
number_format($this->_startno+1),
number_format($this->_endno+1));
// List result
} else {
return sprintf(dngettext(COMMONDOMAIN,
"%s news article, listing %s to %s.",
"%s news articles, listing %s to %s.",
$this->total),
number_format($this->total),
number_format($this->_startno+1),
number_format($this->_endno+1));
}
}
}
}
// LinkCategoriesList: Link categories list handler class
class LinkCategoriesList extends BaseCategoriesList
{
// __construct: Initialize the handler
function __construct($FORM = null, $table = "linkcat")
{
parent::__construct($FORM, $table);
// The page title
$this->title = $this->_is_called_form? C_("Select a Link Category"):
C_("Manage Link Categories");
}
// _coldef: Column definition for non-view usage
function _coldef($col)
{
// Obtain the column definition
switch ($col) {
case "parent":
// Default language
if ($this->_lang == DEFAULT_LANG) {
$title = "parent.title_" . ln($this->_lang, LN_DATABASE);
// Fall back to the default language
} else {
$thiscol = "parent.title_" . ln($this->_lang, LN_DATABASE);
$thiscol = "parent.title_" . ln(DEFAULT_LANG, LN_DATABASE);
$title = "COALESCE(" . $thiscol . ", " . $defcol . ")";
}
return "CASE WHEN " . $this->_table . ".parent IS NOT NULL"
. " THEN $title"
. " ELSE '" . sql_esctext(t_none()) . "' END";
case "hid":
return "CASE WHEN " . sql_is_true($this->_table . "." . $col)
. " THEN '" . sql_esctext(C_("Hidden")) . "'"
. " ELSE '" . sql_esctext(C_("Shown")) . "' END";
default:
return parent::_coldef($col);
}
}
// _sql_join: Get the SQL JOIN phase
function _sql_join()
{
$join = "";
$join .= " LEFT JOIN links AS parent ON " . $this->_table . ".parent=parent.sn";
return $join . parent::_sql_join();
}
}
// LinksList: Links list handler class
class LinksList extends BaseList
{
// __construct: Initialize the handler
function __construct($FORM = null, $table = "links")
{
parent::__construct($FORM, $table);
// The page title
$this->title = $this->_is_called_form? C_("Select a Link"):
C_("Manage Links");
// The default sort order
$this->_DEFAULT_SORTBY = "title";
// Columns that should display its brief instead
$this->_COLS_BRIEF = array("dsc");
}
// _sql_cols: Obtain the SQL columns list phase
function _sql_cols()
{
// Adjust the column list
$this->_cols = array_merge(array("_viewurl"), $this->_cols);
for ($i = 0; $i < count($this->_cols); $i++) {
switch ($this->_cols[$i]) {
// Insert a URL. checker
case "url":
$this->_cols = array_merge(
array_slice($this->_cols, 0, $i+1),
array("_urlcheck"),
array_slice($this->_cols, $i+1));
$i++;
break;
}
}
// Run the parent method
return parent::_sql_cols();
}
// _coldef: Column definition for non-view usage
function _coldef($col)
{
// Obtain the column definition
switch ($col) {
case "_viewurl":
return $this->_table . ".url";
case "_urlcheck":
return $this->_table . ".url";
case "hid":
return "CASE WHEN " . sql_is_true($this->_table . "." . $col)
. " THEN '" . sql_esctext(C_("Hidden")) . "'"
. " ELSE '" . sql_esctext(C_("Shown")) . "' END";
default:
return parent::_coldef($col);
}
}
// _html_newlink: Display a link to add a new item
function _html_newlink($prompt = false)
{
if ($prompt === false) {
$prompt = C_("Add a new related link.");
}
// Run the parent method
return parent::_html_newlink($prompt);
}
// _html_search: Display the search box
function _html_search($prompt = false)
{
if ($prompt === false) {
$prompt = C_("Search for a related link:");
}
// Run the parent method
return parent::_html_search($prompt);
}
// _liststat_message: Return the current list statistics message
function _liststat_message()
{
// No record to list
if ($this->total == 0) {
// Inherit the empty list statistics message
return parent::_liststat_message();
// Fit in one page
} elseif ($this->_pagesize === false || $this->total <= $this->_pagesize) {
// Result comes from a query
if (!is_null($this->_query)) {
return sprintf(dngettext(COMMONDOMAIN,
"Your query found %s related link.",
"Your query found %s related links.",
$this->total),
number_format($this->total));
// List result
} else {
return sprintf(dngettext(COMMONDOMAIN,
"%s related link.",
"%s related links.",
$this->total),
number_format($this->total));
}
// More than one page
} else {
if (!is_null($this->_query)) {
return sprintf(dngettext(COMMONDOMAIN,
"Your query found %s related link, listing %s to %s.",
"Your query found %s related links, listing %s to %s.",
$this->total),
number_format($this->total),
number_format($this->_startno+1),
number_format($this->_endno+1));
// List result
} else {
return sprintf(dngettext(COMMONDOMAIN,
"%s related link, listing %s to %s.",
"%s related links, listing %s to %s.",
$this->total),
number_format($this->total),
number_format($this->_startno+1),
number_format($this->_endno+1));
}
}
}
}
// LinkCategorizationList: Link categorization records list handler class
class LinkCategorizationList extends BaseCategorizationList
{
// __construct: Initialize the handler
function __construct($FORM = null, $table = "linkcatz")
{
parent::__construct($FORM, $table);
// The page title
$this->title = $this->_is_called_form?
C_("Select a Link Categorization Record"):
C_("Manage Link Categorization");
// The default sort order
$this->_DEFAULT_SORTBY = "cat,link";
// Column labels
$this->_col_labels(array(
"link" => C_("Link"),
));
}
// _coldef: Column definition for non-view usage
function _coldef($col)
{
// Obtain the column definition
switch ($col) {
case "cat":
// Default language
if ($this->_lang == DEFAULT_LANG) {
return "linkcat.title_" . ln($this->_lang, LN_DATABASE);
// Fall back to the default language
} else {
$thiscol = "linkcat.title_" . ln($this->_lang, LN_DATABASE);
$thiscol = "linkcat.title_" . ln(DEFAULT_LANG, LN_DATABASE);
return "COALESCE(" . $thiscol . ", " . $defcol . ")";
}
case "link":
// Default language
if ($this->_lang == DEFAULT_LANG) {
return "links.title_" . ln($this->_lang, LN_DATABASE);
// Fall back to the default language
} else {
$thiscol = "links.title_" . ln($this->_lang, LN_DATABASE);
$thiscol = "links.title_" . ln(DEFAULT_LANG, LN_DATABASE);
return "COALESCE(" . $thiscol . ", " . $defcol . ")";
}
case "hid":
return "CASE WHEN " . sql_is_true($this->_table . "." . $col)
. " THEN '" . sql_esctext(C_("Hidden")) . "'"
. " ELSE '" . sql_esctext(C_("Shown")) . "' END";
default:
return parent::_coldef($col);
}
}
// _sql_join: Get the SQL JOIN phase
function _sql_join()
{
$join = "";
$join .= " LEFT JOIN linkcat ON " . $this->_table . ".cat=linkcat.sn";
$join .= " LEFT JOIN links ON " . $this->_table . ".link=links.sn";
return $join . parent::_sql_join();
}
}
// CountriesList: Countries list handler class
class CountriesList extends BaseList
{
// __construct: Initialize the handler
function __construct($FORM = null, $table = "country")
{
parent::__construct($FORM, $table);
// The page title
$this->title = $this->_is_called_form? C_("Select a Country"):
C_("Manage Country Data");
// The default sort order
$this->_DEFAULT_SORTBY = "title";
// Column labels
$this->_col_labels(array(
"id" => C_("Code"),
"name" => C_("Country name"),
"special" => C_("Special?"),
));
}
// _html_newlink: Display a link to add a new item
function _html_newlink($prompt = false)
{
if ($prompt === false) {
$prompt = C_("Add a new country record.");
}
// Run the parent method
return parent::_html_newlink($prompt);
}
// _html_search: Display the search box
function _html_search($prompt = false)
{
if ($prompt === false) {
$prompt = C_("Search for a country:");
}
// Run the parent method
return parent::_html_search($prompt);
}
// _liststat_message: Return the current list statistics message
function _liststat_message()
{
// No record to list
if ($this->total == 0) {
// Inherit the empty list statistics message
return parent::_liststat_message();
// Fit in one page
} elseif ($this->_pagesize === false || $this->total <= $this->_pagesize) {
// Result comes from a query
if (!is_null($this->_query)) {
return sprintf(dngettext(COMMONDOMAIN,
"Your query found %s country.",
"Your query found %s countries.",
$this->total),
number_format($this->total));
// List result
} else {
return sprintf(dngettext(COMMONDOMAIN,
"%s country.",
"%s countries.",
$this->total),
number_format($this->total));
}
// More than one page
} else {
if (!is_null($this->_query)) {
return sprintf(dngettext(COMMONDOMAIN,
"Your query found %s country, listing %s to %s.",
"Your query found %s countries, listing %s to %s.",
$this->total),
number_format($this->total),
number_format($this->_startno+1),
number_format($this->_endno+1));
// List result
} else {
return sprintf(dngettext(COMMONDOMAIN,
"%s country, listing %s to %s.",
"%s countries, listing %s to %s.",
$this->total),
number_format($this->total),
number_format($this->_startno+1),
number_format($this->_endno+1));
}
}
}
}
// ActivityLogList: Activity log list handler class
class ActivityLogList extends BaseList
{
protected $_rdgt = 4;
protected $_rows = 4;
// __construct: Initialize the handler
function __construct($FORM = null, $table = null)
{
parent::__construct($FORM, $table);
// The page title
$this->title = C_("Browse the Activity Log");
$this->_rows = array_key_exists("rows", $this->_form)?
$this->_form["rows"]: null;
$this->_reverse = true;
}
// fetch: Fetch the current list.
function fetch()
{
// Fetched before
if ($this->_fetched) {
return $this->error;
}
$this->_fetched = true;
// Initialize the error status
$this->error = null;
// Check the query phrases
$this->_check_query();
// Check the number of rows to display
$error = $this->_check_pagesize();
if (!is_null($error)) {
if (is_null($this->error)) {
$this->error = $error;
}
$this->_pagesize = $this->_DEFAULT_LIST_SIZE;
} elseif (is_null($this->_rows)) {
$this->_pagesize = $this->_DEFAULT_LIST_SIZE;
} else {
$this->_pagesize = $this->_rows;
}
$fp = fopen(ACTLOG, "r");
flock($fp, LOCK_SH);
$this->_current = array();
// Obtain all the log entries
if (count($this->_query_phrases) == 0) {
while (!feof($fp)) {
$line = fgets($fp);
if ($line === false) {
break;
}
$this->_current[] = $line;
}
// Obtain all the matched log entries
} else {
while (!feof($fp)) {
$line = fgets($fp);
if ($line === false) {
break;
}
for ($i = 0, $matched = true; $i < count($this->_query_phrases); $i++) {
if (stripos($line, $this->_query_phrases[$i]) === false) {
$matched = false;
break;
}
}
if ($matched) {
$this->_current[] = $line;
}
}
}
flock($fp, LOCK_UN);
fclose($fp);
$this->total = count($this->_current);
$this->_endno = $this->total - 1;
$this->_startno = 1;
if ($this->total > $this->_pagesize) {
$this->_startno = $this->_endno - $this->_pagesize + 1;
$this->_current = array_slice($this->_current, $this->_startno);
}
$this->_current = array_reverse($this->_current);
// Done
return $this->error;
}
// _check_query: Check the query phrases
function _check_query()
{
// No query, return
if (is_null($this->_query)) {
return;
}
// Regularize it
$this->_query = trim($this->_query);
// Check if it is filled
if ($this->_query == "") {
$this->_query = null;
return;
}
$this->_query_phrases = parse_query($this->_query);
return;
}
// _check_pagesize: Check the number of rows to display
function _check_pagesize()
{
// No rows, return
if (is_null($this->_rows)) {
return null;
}
$min = 0;
$max = pow(10, $this->_rdgt) - 1;
// Text string
if (is_string($this->_rows)) {
// Regularize it
$this->_rows = trim($this->_rows);
// Check if it is filled
if ($this->_rows == "") {
return array("msg"=>NC_("Please fill in the number of rows to display."));
}
// Check the length
if (sql_strlen($this->_rows) > $this->_rdgt) {
return array("msg"=>NC_("This number of rows to display is too long. (Max. length %d)"),
"margs"=>array($this->_rdgt));
}
// If there is any non-digit character
if (preg_match("/\D/", $this->_rows)) {
return array("msg"=>NC_("Please fill in a positive integer number of rows to display."));
}
// Check if it is in the valid range
if ($this->_rows < $min) {
return array("msg"=>NC_("The number of rows to display is too small. Please fill in a larger number of rows to display between %d and %d."),
"margs"=>array($min, $max));
}
// It is not possible to be too large now.
// Convert its type to integer
settype($this->_rows, "integer");
// Integer
} elseif (is_int($this->_rows)) {
// Check if it is in the valid range
if ($this->_rows < $min) {
return array("msg"=>NC_("The number of rows to display is too small. Please fill in a larger number of rows to display between %d and %d."),
"margs"=>array($min, $max));
}
if ($this->_rows > $max) {
return array("msg"=>NC_("The number of rows to display is too large. Please fill in a smaller number of rows to display between %d and %d."),
"margs"=>array($min, $max));
}
// Other types are non-sense
} else {
trigger_error("Unknown type for column \"rows\"", E_USER_ERROR);
}
// OK
return null;
}
// _html_newlink: Display a link to add a new item
function _html_newlink($prompt = false)
{
if ($prompt === false) {
$prompt = null;
}
// Run the parent method
return parent::_html_newlink($prompt);
}
// _html_search: Display the search box
function _html_search($prompt = false)
{
if ($prompt === false) {
$prompt = C_("Search for log entries:");
}
$label = C_("Display");
$defquery = C_("(query phrase)");
$query = !is_null($this->_query) && $this->_query != ""?
$this->_query: $defquery;
$rows = (!is_null($this->_rows)?
$this->_rows: $this->_DEFAULT_LIST_SIZE);
?><form action="<?php echo h(REQUEST_FILE); ?>" method="get"
accept-charset="<!--monica:charset-->">
<div class="searchbox">
<label for="query"><?php echo h($prompt); ?></label><input
id="query" type="text" name="query" value="<?php echo h($query); ?>"
onfocus="if (this.value == &quot;<?php echo h($defquery); ?>&quot;) this.value = &quot;&quot;;" />
<label for="rows"><?php echo h(C_("Display rows:")); ?></label><input
id="rows" type="text" name="rows" size="<?php echo h($this->_rdgt); ?>" maxlength="<?php echo h($this->_rdgt); ?>" value="<?php echo h($rows); ?>" />
<input type="hidden" name="charset" value="<!--monica:charset-->" />
<input type="submit" value="<?php echo h($label); ?>" />
</div>
</form>
<?php
return;
}
// _liststat_message: Return the current list statistics message
function _liststat_message()
{
// No record to list
if ($this->total == 0) {
// Inherit the empty list statistics message
return parent::_liststat_message();
// Fit in one page
} elseif ($this->_pagesize === false || $this->total <= $this->_pagesize) {
// Result comes from a query
if (!is_null($this->_query)) {
return sprintf(dngettext(COMMONDOMAIN,
"Your query found %s log entry.",
"Your query found %s log entries.",
$this->total),
number_format($this->total));
// List result
} else {
return sprintf(dngettext(COMMONDOMAIN,
"%s log entry.",
"%s log entries.",
$this->total),
number_format($this->total));
}
// More than one page
} else {
if (!is_null($this->_query)) {
return sprintf(dngettext(COMMONDOMAIN,
"Your query found %s log entry, listing %s to %s.",
"Your query found %s log entries, listing %s to %s.",
$this->total),
number_format($this->total),
number_format($this->_startno+1),
number_format($this->_endno+1));
// List result
} else {
return sprintf(dngettext(COMMONDOMAIN,
"%s log entry, listing %s to %s.",
"%s log entries, listing %s to %s.",
$this->total),
number_format($this->total),
number_format($this->_startno+1),
number_format($this->_endno+1));
}
}
}
// _html_pagebar: Display a page navigation bar
// Make it a null function
function _html_pagebar()
{
return;
}
// _html_list: List the items
function _html_list()
{
// Don't show the list
if (is_null($this->total)) {
return;
}
// No record to be listed
if ($this->total == 0) {
return;
}
$html = implode("", $this->_current);
$html = preg_replace_callback("/([\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F])/",
function ($matches) {
return sprintf("\\x%02x", ord($matches[1]));
}, $html);
?><div>
<?php
echo a2html($html);
?></div>
<?php
return;
}
// _html_listprefform: Display a form to change the list preference
// Make it a null function
function _html_listprefform()
{
return;
}
}
?>