1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171
|
<?php rcs_id('$Id: Theme.php,v 1.142 2007/07/01 09:36:09 rurban Exp $');
/* Copyright (C) 2002,2004,2005,2006 $ThePhpWikiProgrammingTeam
*
* This file is part of PhpWiki.
*
* PhpWiki is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* PhpWiki is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PhpWiki; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/**
* Customize output by themes: templates, css, special links functions,
* and more formatting.
*/
require_once(dirname(__FILE__).'/HtmlElement.php');
/**
* Make a link to a wiki page (in this wiki).
*
* This is a convenience function.
*
* @param mixed $page_or_rev
* Can be:<dl>
* <dt>A string</dt><dd>The page to link to.</dd>
* <dt>A WikiDB_Page object</dt><dd>The page to link to.</dd>
* <dt>A WikiDB_PageRevision object</dt><dd>A specific version of the page to link to.</dd>
* </dl>
*
* @param string $type
* One of:<dl>
* <dt>'unknown'</dt><dd>Make link appropriate for a non-existant page.</dd>
* <dt>'known'</dt><dd>Make link appropriate for an existing page.</dd>
* <dt>'auto'</dt><dd>Either 'unknown' or 'known' as appropriate.</dd>
* <dt>'button'</dt><dd>Make a button-style link.</dd>
* <dt>'if_known'</dt><dd>Only linkify if page exists.</dd>
* </dl>
* Unless $type of of the latter form, the link will be of class 'wiki', 'wikiunknown',
* 'named-wiki', or 'named-wikiunknown', as appropriate.
*
* @param mixed $label (string or XmlContent object)
* Label for the link. If not given, defaults to the page name.
*
* @return XmlContent The link
*/
function WikiLink ($page_or_rev, $type = 'known', $label = false) {
global $WikiTheme, $request;
if ($type == 'button') {
return $WikiTheme->makeLinkButton($page_or_rev, $label);
}
$version = false;
if (isa($page_or_rev, 'WikiDB_PageRevision')) {
$version = $page_or_rev->getVersion();
if ($page_or_rev->isCurrent())
$version = false;
$page = $page_or_rev->getPage();
$pagename = $page->getName();
$wikipage = $pagename;
$exists = true;
}
elseif (isa($page_or_rev, 'WikiDB_Page')) {
$page = $page_or_rev;
$pagename = $page->getName();
$wikipage = $pagename;
}
elseif (isa($page_or_rev, 'WikiPageName')) {
$wikipage = $page_or_rev;
$pagename = $wikipage->name;
if (!$wikipage->isValid('strict'))
return $WikiTheme->linkBadWikiWord($wikipage, $label);
}
else {
$wikipage = new WikiPageName($page_or_rev, $request->getPage());
$pagename = $wikipage->name;
if (!$wikipage->isValid('strict'))
return $WikiTheme->linkBadWikiWord($wikipage, $label);
}
if ($type == 'auto' or $type == 'if_known') {
if (isset($page)) {
$exists = $page->exists();
}
else {
$dbi =& $request->_dbi;
$exists = $dbi->isWikiPage($wikipage->name);
}
}
elseif ($type == 'unknown') {
$exists = false;
}
else {
$exists = true;
}
// FIXME: this should be somewhere else, if really needed.
// WikiLink makes A link, not a string of fancy ones.
// (I think that the fancy split links are just confusing.)
// Todo: test external ImageLinks http://some/images/next.gif
if (isa($wikipage, 'WikiPageName') and
! $label and
strchr(substr($wikipage->shortName,1), SUBPAGE_SEPARATOR))
{
$parts = explode(SUBPAGE_SEPARATOR, $wikipage->shortName);
$last_part = array_pop($parts);
$sep = '';
$link = HTML::span();
foreach ($parts as $part) {
$path[] = $part;
$parent = join(SUBPAGE_SEPARATOR, $path);
if ($WikiTheme->_autosplitWikiWords)
$part = " " . $part;
if ($part)
$link->pushContent($WikiTheme->linkExistingWikiWord($parent, $sep . $part));
$sep = $WikiTheme->_autosplitWikiWords
? ' ' . SUBPAGE_SEPARATOR : SUBPAGE_SEPARATOR;
}
if ($exists)
$link->pushContent($WikiTheme->linkExistingWikiWord($wikipage, $sep . $last_part,
$version));
else
$link->pushContent($WikiTheme->linkUnknownWikiWord($wikipage, $sep . $last_part));
return $link;
}
if ($exists) {
return $WikiTheme->linkExistingWikiWord($wikipage, $label, $version);
}
elseif ($type == 'if_known') {
if (!$label && isa($wikipage, 'WikiPageName'))
$label = $wikipage->shortName;
return HTML($label ? $label : $pagename);
}
else {
return $WikiTheme->linkUnknownWikiWord($wikipage, $label);
}
}
/**
* Make a button.
*
* This is a convenience function.
*
* @param $action string
* One of <dl>
* <dt>[action]</dt><dd>Perform action (e.g. 'edit') on the selected page.</dd>
* <dt>[ActionPage]</dt><dd>Run the actionpage (e.g. 'BackLinks') on the selected page.</dd>
* <dt>'submit:'[name]</dt><dd>Make a form submission button with the given name.
* ([name] can be blank for a nameless submit button.)</dd>
* <dt>a hash</dt><dd>Query args for the action. E.g.<pre>
* array('action' => 'diff', 'previous' => 'author')
* </pre></dd>
* </dl>
*
* @param $label string
* A label for the button. If ommited, a suitable default (based on the valued of $action)
* will be picked.
*
* @param $page_or_rev mixed
* Which page (& version) to perform the action on.
* Can be one of:<dl>
* <dt>A string</dt><dd>The pagename.</dd>
* <dt>A WikiDB_Page object</dt><dd>The page.</dd>
* <dt>A WikiDB_PageRevision object</dt><dd>A specific version of the page.</dd>
* </dl>
* ($Page_or_rev is ignored for submit buttons.)
*/
function Button ($action, $label = false, $page_or_rev = false, $options = false) {
global $WikiTheme;
if (!is_array($action) && preg_match('/^submit:(.*)/', $action, $m))
return $WikiTheme->makeSubmitButton($label, $m[1], $page_or_rev, $options);
else
return $WikiTheme->makeActionButton($action, $label, $page_or_rev, $options);
}
class Theme {
var $HTML_DUMP_SUFFIX = '';
var $DUMP_MODE = false, $dumped_images, $dumped_css;
/**
* noinit: Do not initialize unnecessary items in default_theme fallback twice.
*/
function Theme ($theme_name = 'default', $noinit = false) {
$this->_name = $theme_name;
$this->_themes_dir = NormalizeLocalFileName("themes");
$this->_path = defined('PHPWIKI_DIR') ? NormalizeLocalFileName("") : "";
$this->_theme = "themes/$theme_name";
if ($theme_name != 'default')
$this->_default_theme = new Theme('default',true);
if ($noinit) return;
$this->addMoreHeaders(JavaScript("var data_path = '". DATA_PATH ."'\n"
."var pagename = '". $GLOBALS['request']->getArg('pagename') ."'\n"
."var stylepath = '". DATA_PATH . '/'.$this->_theme."/'\n"));
// by pixels
if ((is_object($GLOBALS['request']) // guard against unittests
and $GLOBALS['request']->getPref('doubleClickEdit'))
or ENABLE_DOUBLECLICKEDIT)
$this->initDoubleClickEdit();
// will be replaced by acDropDown
if (ENABLE_LIVESEARCH) { // by bitflux.ch
$this->initLiveSearch();
}
// replaces external LiveSearch
if (defined("ENABLE_ACDROPDOWN") and ENABLE_ACDROPDOWN) {
$this->initMoAcDropDown();
}
$this->_css = array();
}
function file ($file) {
return $this->_path . "$this->_theme/$file";
}
function _findFile ($file, $missing_okay = false) {
if (file_exists($this->file($file)))
return "$this->_theme/$file";
// FIXME: this is a short-term hack. Delete this after all files
// get moved into themes/...
if (file_exists($this->_path . $file))
return $file;
if (isset($this->_default_theme)) {
return $this->_default_theme->_findFile($file, $missing_okay);
}
else if (!$missing_okay) {
if (DEBUG & function_exists('debug_backtrace')) { // >= 4.3.0
echo "<pre>", printSimpleTrace(debug_backtrace()), "</pre>\n";
}
trigger_error("$this->_theme/$file: not found", E_USER_NOTICE);
}
return false;
}
function _findData ($file, $missing_okay = false) {
$path = $this->_findFile($file, $missing_okay);
if (!$path)
return false;
if (defined('DATA_PATH'))
return DATA_PATH . "/$path";
return $path;
}
////////////////////////////////////////////////////////////////
//
// Date and Time formatting
//
////////////////////////////////////////////////////////////////
// Note: Windows' implemetation of strftime does not include certain
// format specifiers, such as %e (for date without leading zeros). In
// general, see:
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_crt_strftime.2c_.wcsftime.asp
// As a result, we have to use %d, and strip out leading zeros ourselves.
var $_dateFormat = "%B %d, %Y";
var $_timeFormat = "%I:%M %p";
var $_showModTime = true;
/**
* Set format string used for dates.
*
* @param $fs string Format string for dates.
*
* @param $show_mod_time bool If true (default) then times
* are included in the messages generated by getLastModifiedMessage(),
* otherwise, only the date of last modification will be shown.
*/
function setDateFormat ($fs, $show_mod_time = true) {
$this->_dateFormat = $fs;
$this->_showModTime = $show_mod_time;
}
/**
* Set format string used for times.
*
* @param $fs string Format string for times.
*/
function setTimeFormat ($fs) {
$this->_timeFormat = $fs;
}
/**
* Format a date.
*
* Any time zone offset specified in the users preferences is
* taken into account by this method.
*
* @param $time_t integer Unix-style time.
*
* @return string The date.
*/
function formatDate ($time_t) {
global $request;
$offset_time = $time_t + 3600 * $request->getPref('timeOffset');
// strip leading zeros from date elements (ie space followed by zero)
return preg_replace('/ 0/', ' ',
strftime($this->_dateFormat, $offset_time));
}
/**
* Format a date.
*
* Any time zone offset specified in the users preferences is
* taken into account by this method.
*
* @param $time_t integer Unix-style time.
*
* @return string The time.
*/
function formatTime ($time_t) {
//FIXME: make 24-hour mode configurable?
global $request;
$offset_time = $time_t + 3600 * $request->getPref('timeOffset');
return preg_replace('/^0/', ' ',
strtolower(strftime($this->_timeFormat, $offset_time)));
}
/**
* Format a date and time.
*
* Any time zone offset specified in the users preferences is
* taken into account by this method.
*
* @param $time_t integer Unix-style time.
*
* @return string The date and time.
*/
function formatDateTime ($time_t) {
return $this->formatDate($time_t) . ' ' . $this->formatTime($time_t);
}
/**
* Format a (possibly relative) date.
*
* If enabled in the users preferences, this method might
* return a relative day (e.g. 'Today', 'Yesterday').
*
* Any time zone offset specified in the users preferences is
* taken into account by this method.
*
* @param $time_t integer Unix-style time.
*
* @return string The day.
*/
function getDay ($time_t) {
global $request;
if ($request->getPref('relativeDates') && ($date = $this->_relativeDay($time_t))) {
return ucfirst($date);
}
return $this->formatDate($time_t);
}
/**
* Format the "last modified" message for a page revision.
*
* @param $revision object A WikiDB_PageRevision object.
*
* @param $show_version bool Should the page version number
* be included in the message. (If this argument is omitted,
* then the version number will be shown only iff the revision
* is not the current one.
*
* @return string The "last modified" message.
*/
function getLastModifiedMessage ($revision, $show_version = 'auto') {
global $request;
if (!$revision) return '';
// dates >= this are considered invalid.
if (! defined('EPOCH'))
define('EPOCH', 0); // seconds since ~ January 1 1970
$mtime = $revision->get('mtime');
if ($mtime <= EPOCH)
return fmt("Never edited");
if ($show_version == 'auto')
$show_version = !$revision->isCurrent();
if ($request->getPref('relativeDates') && ($date = $this->_relativeDay($mtime))) {
if ($this->_showModTime)
$date = sprintf(_("%s at %s"),
$date, $this->formatTime($mtime));
if ($show_version)
return fmt("Version %s, saved %s", $revision->getVersion(), $date);
else
return fmt("Last edited %s", $date);
}
if ($this->_showModTime)
$date = $this->formatDateTime($mtime);
else
$date = $this->formatDate($mtime);
if ($show_version)
return fmt("Version %s, saved on %s", $revision->getVersion(), $date);
else
return fmt("Last edited on %s", $date);
}
function _relativeDay ($time_t) {
global $request;
if (is_numeric($request->getPref('timeOffset')))
$offset = 3600 * $request->getPref('timeOffset');
else
$offset = 0;
$now = time() + $offset;
$today = localtime($now, true);
$time = localtime($time_t + $offset, true);
if ($time['tm_yday'] == $today['tm_yday'] && $time['tm_year'] == $today['tm_year'])
return _("today");
// Note that due to daylight savings chages (and leap seconds), $now minus
// 24 hours is not guaranteed to be yesterday.
$yesterday = localtime($now - (12 + $today['tm_hour']) * 3600, true);
if ($time['tm_yday'] == $yesterday['tm_yday']
and $time['tm_year'] == $yesterday['tm_year'])
return _("yesterday");
return false;
}
/**
* Format the "Author" and "Owner" messages for a page revision.
*/
function getOwnerMessage ($page) {
if (!ENABLE_PAGEPERM or !class_exists("PagePermission"))
return '';
$dbi =& $GLOBALS['request']->_dbi;
$owner = $page->getOwner();
if ($owner) {
/*
if ( mayAccessPage('change',$page->getName()) )
return fmt("Owner: %s", $this->makeActionButton(array('action'=>_("chown"),
's' => $page->getName()),
$owner, $page));
*/
if ( $dbi->isWikiPage($owner) )
return fmt("Owner: %s", WikiLink($owner));
else
return fmt("Owner: %s", '"'.$owner.'"');
}
}
/* New behaviour: (by Matt Brown)
Prefer author (name) over internal author_id (IP) */
function getAuthorMessage ($revision) {
if (!$revision) return '';
$dbi =& $GLOBALS['request']->_dbi;
$author = $revision->get('author');
if (!$author) $author = $revision->get('author_id');
if (!$author) return '';
if ( $dbi->isWikiPage($author) ) {
return fmt("by %s", WikiLink($author));
} else {
return fmt("by %s", '"'.$author.'"');
}
}
////////////////////////////////////////////////////////////////
//
// Hooks for other formatting
//
////////////////////////////////////////////////////////////////
//FIXME: PHP 4.1 Warnings
//lib/Theme.php:84: Notice[8]: The call_user_method() function is deprecated,
//use the call_user_func variety with the array(&$obj, "method") syntax instead
function getFormatter ($type, $format) {
$method = strtolower("get${type}Formatter");
if (method_exists($this, $method))
return $this->{$method}($format);
return false;
}
////////////////////////////////////////////////////////////////
//
// Links
//
////////////////////////////////////////////////////////////////
var $_autosplitWikiWords = false;
function setAutosplitWikiWords($autosplit=true) {
$this->_autosplitWikiWords = $autosplit ? true : false;
}
function maybeSplitWikiWord ($wikiword) {
if ($this->_autosplitWikiWords)
return SplitPagename($wikiword);
else
return $wikiword;
}
var $_anonEditUnknownLinks = true;
function setAnonEditUnknownLinks($anonedit=true) {
$this->_anonEditUnknownLinks = $anonedit ? true : false;
}
function linkExistingWikiWord($wikiword, $linktext = '', $version = false) {
global $request;
if ($version !== false and !$this->HTML_DUMP_SUFFIX)
$url = WikiURL($wikiword, array('version' => $version));
else
$url = WikiURL($wikiword);
// Extra steps for dumping page to an html file.
if ($this->HTML_DUMP_SUFFIX) {
$url = preg_replace('/^\./', '%2e', $url); // dot pages
}
$link = HTML::a(array('href' => $url));
if (isa($wikiword, 'WikiPageName'))
$default_text = $wikiword->shortName;
else
$default_text = $wikiword;
if (!empty($linktext)) {
$link->pushContent($linktext);
$link->setAttr('class', 'named-wiki');
$link->setAttr('title', $this->maybeSplitWikiWord($default_text));
}
else {
$link->pushContent($this->maybeSplitWikiWord($default_text));
$link->setAttr('class', 'wiki');
}
if ($request->getArg('frame'))
$link->setAttr('target', '_top');
return $link;
}
function linkUnknownWikiWord($wikiword, $linktext = '') {
global $request;
// Get rid of anchors on unknown wikiwords
if (isa($wikiword, 'WikiPageName')) {
$default_text = $wikiword->shortName;
$wikiword = $wikiword->name;
}
else {
$default_text = $wikiword;
}
if ($this->DUMP_MODE) { // HTML, PDF or XML
$link = HTML::u( empty($linktext) ? $wikiword : $linktext);
$link->addTooltip(sprintf(_("Empty link to: %s"), $wikiword));
$link->setAttr('class', empty($linktext) ? 'wikiunknown' : 'named-wikiunknown');
return $link;
} else {
// if AnonEditUnknownLinks show "?" only users which are allowed to edit this page
if (! $this->_anonEditUnknownLinks and
( ! $request->_user->isSignedIn()
or ! mayAccessPage('edit', $request->getArg('pagename'))))
{
$text = HTML::span( empty($linktext) ? $wikiword : $linktext);
$text->setAttr('class', empty($linktext) ? 'wikiunknown' : 'named-wikiunknown');
return $text;
} else {
$url = WikiURL($wikiword, array('action' => 'create'));
$button = $this->makeButton('?', $url);
$button->addTooltip(sprintf(_("Create: %s"), $wikiword));
}
}
$link = HTML::span();
if (!empty($linktext)) {
$link->pushContent(HTML::u($linktext));
$link->setAttr('class', 'named-wikiunknown');
}
else {
$link->pushContent(HTML::u($this->maybeSplitWikiWord($default_text)));
$link->setAttr('class', 'wikiunknown');
}
if (!isa($button, "ImageButton"))
$button->setAttr('rel', 'nofollow');
$link->pushContent($button);
if ($request->getPref('googleLink')) {
$gbutton = $this->makeButton('G', "http://www.google.com/search?q="
. urlencode($wikiword));
$gbutton->addTooltip(sprintf(_("Google:%s"), $wikiword));
$link->pushContent($gbutton);
}
if ($request->getArg('frame'))
$link->setAttr('target', '_top');
return $link;
}
function linkBadWikiWord($wikiword, $linktext = '') {
global $ErrorManager;
if ($linktext) {
$text = $linktext;
}
elseif (isa($wikiword, 'WikiPageName')) {
$text = $wikiword->shortName;
}
else {
$text = $wikiword;
}
if (isa($wikiword, 'WikiPageName'))
$message = $wikiword->getWarnings();
else
$message = sprintf(_("'%s': Bad page name"), $wikiword);
$ErrorManager->warning($message);
return HTML::span(array('class' => 'badwikiword'), $text);
}
////////////////////////////////////////////////////////////////
//
// Images and Icons
//
////////////////////////////////////////////////////////////////
var $_imageAliases = array();
var $_imageAlt = array();
/**
*
* (To disable an image, alias the image to <code>false</code>.
*/
function addImageAlias ($alias, $image_name) {
// fall back to the PhpWiki-supplied image if not found
if ((empty($this->_imageAliases[$alias])
and $this->_findFile("images/$image_name", true))
or $image_name === false)
$this->_imageAliases[$alias] = $image_name;
}
function addImageAlt ($alias, $alt_text) {
$this->_imageAlt[$alias] = $alt_text;
}
function getImageAlt ($alias) {
return $this->_imageAlt[$alias];
}
function getImageURL ($image) {
$aliases = &$this->_imageAliases;
if (isset($aliases[$image])) {
$image = $aliases[$image];
if (!$image)
return false;
}
// If not extension, default to .png.
if (!preg_match('/\.\w+$/', $image))
$image .= '.png';
// FIXME: this should probably be made to fall back
// automatically to .gif, .jpg.
// Also try .gif before .png if browser doesn't like png.
$path = $this->_findData("images/$image", 'missing okay');
if (!$path) // search explicit images/ or button/ links also
$path = $this->_findData("$image", 'missing okay');
if ($this->DUMP_MODE) {
if (empty($this->dumped_images)) $this->dumped_images = array();
$path = "images/". basename($path);
if (!in_array($path,$this->dumped_images))
$this->dumped_images[] = $path;
}
return $path;
}
function setLinkIcon($proto, $image = false) {
if (!$image)
$image = $proto;
$this->_linkIcons[$proto] = $image;
}
function getLinkIconURL ($proto) {
$icons = &$this->_linkIcons;
if (!empty($icons[$proto]))
return $this->getImageURL($icons[$proto]);
elseif (!empty($icons['*']))
return $this->getImageURL($icons['*']);
return false;
}
var $_linkIcon = 'front'; // or 'after' or 'no'.
// maybe also 'spanall': there is a scheme currently in effect with front, which
// spans the icon only to the first, to let the next words wrap on line breaks
// see stdlib.php:PossiblyGlueIconToText()
function getLinkIconAttr () {
return $this->_linkIcon;
}
function setLinkIconAttr ($where) {
$this->_linkIcon = $where;
}
function addButtonAlias ($text, $alias = false) {
$aliases = &$this->_buttonAliases;
if (is_array($text))
$aliases = array_merge($aliases, $text);
elseif ($alias === false)
unset($aliases[$text]);
else
$aliases[$text] = $alias;
}
function getButtonURL ($text) {
$aliases = &$this->_buttonAliases;
if (isset($aliases[$text]))
$text = $aliases[$text];
$qtext = urlencode($text);
$url = $this->_findButton("$qtext.png");
if ($url && strstr($url, '%')) {
$url = preg_replace('|([^/]+)$|e', 'urlencode("\\1")', $url);
}
if (!$url) {// Jeff complained about png not supported everywhere.
// This was not PC until 2005.
$url = $this->_findButton("$qtext.gif");
if ($url && strstr($url, '%')) {
$url = preg_replace('|([^/]+)$|e', 'urlencode("\\1")', $url);
}
}
if ($url and $this->DUMP_MODE) {
if (empty($this->dumped_buttons)) $this->dumped_buttons = array();
$file = $url;
if (defined('DATA_PATH'))
$file = substr($url,strlen(DATA_PATH)+1);
$url = "images/buttons/".basename($file);
if (!array_key_exists($text, $this->dumped_buttons))
$this->dumped_buttons[$text] = $file;
}
return $url;
}
function _findButton ($button_file) {
if (empty($this->_button_path))
$this->_button_path = $this->_getButtonPath();
foreach ($this->_button_path as $dir) {
if ($path = $this->_findData("$dir/$button_file", 1))
return $path;
}
return false;
}
function _getButtonPath () {
$button_dir = $this->_findFile("buttons");
$path_dir = $this->_path . $button_dir;
if (!file_exists($path_dir) || !is_dir($path_dir))
return array();
$path = array($button_dir);
$dir = dir($path_dir);
while (($subdir = $dir->read()) !== false) {
if ($subdir[0] == '.')
continue;
if ($subdir == 'CVS')
continue;
if (is_dir("$path_dir/$subdir"))
$path[] = "$button_dir/$subdir";
}
$dir->close();
// add default buttons
$path[] = "themes/default/buttons";
$path_dir = $this->_path . "themes/default/buttons";
$dir = dir($path_dir);
while (($subdir = $dir->read()) !== false) {
if ($subdir[0] == '.')
continue;
if ($subdir == 'CVS')
continue;
if (is_dir("$path_dir/$subdir"))
$path[] = "themes/default/buttons/$subdir";
}
$dir->close();
return $path;
}
////////////////////////////////////////////////////////////////
//
// Button style
//
////////////////////////////////////////////////////////////////
function makeButton ($text, $url, $class = false, $options = false) {
// FIXME: don't always try for image button?
// Special case: URLs like 'submit:preview' generate form
// submission buttons.
if (preg_match('/^submit:(.*)$/', $url, $m))
return $this->makeSubmitButton($text, $m[1], $class, $options);
$imgurl = $this->getButtonURL($text);
if ($imgurl)
return new ImageButton($text, $url, $class, $imgurl, $options);
else
return new Button($this->maybeSplitWikiWord($text), $url,
$class, $options);
}
function makeSubmitButton ($text, $name, $class = false, $options = false) {
$imgurl = $this->getButtonURL($text);
if ($imgurl)
return new SubmitImageButton($text, $name, $class, $imgurl, $options);
else
return new SubmitButton($text, $name, $class, $options);
}
/**
* Make button to perform action.
*
* This constructs a button which performs an action on the
* currently selected version of the current page.
* (Or anotherpage or version, if you want...)
*
* @param $action string The action to perform (e.g. 'edit', 'lock').
* This can also be the name of an "action page" like 'LikePages'.
* Alternatively you can give a hash of query args to be applied
* to the page.
*
* @param $label string Textual label for the button. If left empty,
* a suitable name will be guessed.
*
* @param $page_or_rev mixed The page to link to. This can be
* given as a string (the page name), a WikiDB_Page object, or as
* WikiDB_PageRevision object. If given as a WikiDB_PageRevision
* object, the button will link to a specific version of the
* designated page, otherwise the button links to the most recent
* version of the page.
*
* @return object A Button object.
*/
function makeActionButton ($action, $label = false, $page_or_rev = false, $options = false) {
extract($this->_get_name_and_rev($page_or_rev));
if (is_array($action)) {
$attr = $action;
$action = isset($attr['action']) ? $attr['action'] : 'browse';
}
else
$attr['action'] = $action;
$class = is_safe_action($action) ? 'wikiaction' : 'wikiadmin';
if ( !$label )
$label = $this->_labelForAction($action);
if ($version)
$attr['version'] = $version;
if ($action == 'browse')
unset($attr['action']);
$options = $this->fixAccesskey($options);
return $this->makeButton($label, WikiURL($pagename, $attr), $class, $options);
}
function tooltipAccessKeyPrefix() {
static $tooltipAccessKeyPrefix = null;
if ($tooltipAccessKeyPrefix) return $tooltipAccessKeyPrefix;
$tooltipAccessKeyPrefix = 'alt';
if (isBrowserOpera()) $tooltipAccessKeyPrefix = 'shift-esc';
elseif (isBrowserSafari() or browserDetect("Mac") or isBrowserKonqueror())
$tooltipAccessKeyPrefix = 'ctrl';
// ff2 win and x11 only
elseif ((browserDetect("firefox/2") or browserDetect("minefield/3") or browserDetect("SeaMonkey/1.1"))
and ((browserDetect("windows") or browserDetect("x11"))))
$tooltipAccessKeyPrefix = 'alt-shift';
return $tooltipAccessKeyPrefix;
}
/** Define the accesskey in the title only, with ending [p] or [alt-p].
* This fixes the prefix in the title and sets the accesskey.
*/
function fixAccesskey($attrs) {
if (!empty($attrs['title']) and preg_match("/\[(alt-)?(.)\]$/", $attrs['title'], $m))
{
if (empty($attrs['accesskey'])) $attrs['accesskey'] = $m[2];
// firefox 'alt-shift', MSIE: 'alt', ... see wikibits.js
$attrs['title'] = preg_replace("/\[(alt-)?(.)\]$/", "[".$this->tooltipAccessKeyPrefix()."-\\2]", $attrs['title']);
}
return $attrs;
}
/**
* Make a "button" which links to a wiki-page.
*
* These are really just regular WikiLinks, possibly
* disguised (e.g. behind an image button) by the theme.
*
* This method should probably only be used for links
* which appear in page navigation bars, or similar places.
*
* Use linkExistingWikiWord, or LinkWikiWord for normal links.
*
* @param $page_or_rev mixed The page to link to. This can be
* given as a string (the page name), a WikiDB_Page object, or as
* WikiDB_PageRevision object. If given as a WikiDB_PageRevision
* object, the button will link to a specific version of the
* designated page, otherwise the button links to the most recent
* version of the page.
*
* @return object A Button object.
*/
function makeLinkButton ($page_or_rev, $label = false, $action = false) {
extract($this->_get_name_and_rev($page_or_rev));
$args = $version ? array('version' => $version) : false;
if ($action) $args['action'] = $action;
return $this->makeButton($label ? $label : $pagename,
WikiURL($pagename, $args), 'wiki');
}
function _get_name_and_rev ($page_or_rev) {
$version = false;
if (empty($page_or_rev)) {
global $request;
$pagename = $request->getArg("pagename");
$version = $request->getArg("version");
}
elseif (is_object($page_or_rev)) {
if (isa($page_or_rev, 'WikiDB_PageRevision')) {
$rev = $page_or_rev;
$page = $rev->getPage();
if (!$rev->isCurrent()) $version = $rev->getVersion();
}
else {
$page = $page_or_rev;
}
$pagename = $page->getName();
}
elseif (is_numeric($page_or_rev)) {
$version = $page_or_rev;
}
else {
$pagename = (string) $page_or_rev;
}
return compact('pagename', 'version');
}
function _labelForAction ($action) {
switch ($action) {
case 'edit': return _("Edit");
case 'diff': return _("Diff");
case 'logout': return _("Sign Out");
case 'login': return _("Sign In");
case 'lock': return _("Lock Page");
case 'unlock': return _("Unlock Page");
case 'remove': return _("Remove Page");
default:
// I don't think the rest of these actually get used.
// 'setprefs'
// 'upload' 'dumpserial' 'loadfile' 'zip'
// 'save' 'browse'
return gettext(ucfirst($action));
}
}
//----------------------------------------------------------------
var $_buttonSeparator = "\n | ";
function setButtonSeparator($separator) {
$this->_buttonSeparator = $separator;
}
function getButtonSeparator() {
return $this->_buttonSeparator;
}
////////////////////////////////////////////////////////////////
//
// CSS
//
// Notes:
//
// Based on testing with Galeon 1.2.7 (Mozilla 1.2):
// Automatic media-based style selection (via <link> tags) only
// seems to work for the default style, not for alternate styles.
//
// Doing
//
// <link rel="stylesheet" type="text/css" href="phpwiki.css" />
// <link rel="stylesheet" type="text/css" href="phpwiki-printer.css" media="print" />
//
// works to make it so that the printer style sheet get used
// automatically when printing (or print-previewing) a page
// (but when only when the default style is selected.)
//
// Attempts like:
//
// <link rel="alternate stylesheet" title="Modern"
// type="text/css" href="phpwiki-modern.css" />
// <link rel="alternate stylesheet" title="Modern"
// type="text/css" href="phpwiki-printer.css" media="print" />
//
// Result in two "Modern" choices when trying to select alternate style.
// If one selects the first of those choices, one gets phpwiki-modern
// both when browsing and printing. If one selects the second "Modern",
// one gets no CSS when browsing, and phpwiki-printer when printing.
//
// The Real Fix?
// =============
//
// We should probably move to doing the media based style
// switching in the CSS files themselves using, e.g.:
//
// @import url(print.css) print;
//
////////////////////////////////////////////////////////////////
function _CSSlink($title, $css_file, $media, $is_alt = false) {
// Don't set title on default style. This makes it clear to
// the user which is the default (i.e. most supported) style.
if ($is_alt and isBrowserKonqueror())
return HTML();
$link = HTML::link(array('rel' => $is_alt ? 'alternate stylesheet' : 'stylesheet',
'type' => 'text/css',
'charset' => $GLOBALS['charset'],
'href' => $this->_findData($css_file)));
if ($is_alt)
$link->setAttr('title', $title);
if ($media)
$link->setAttr('media', $media);
if ($this->DUMP_MODE) {
if (empty($this->dumped_css)) $this->dumped_css = array();
if (!in_array($css_file,$this->dumped_css)) $this->dumped_css[] = $css_file;
$link->setAttr('href', basename($link->getAttr('href')));
}
return $link;
}
/** Set default CSS source for this theme.
*
* To set styles to be used for different media, pass a
* hash for the second argument, e.g.
*
* $theme->setDefaultCSS('default', array('' => 'normal.css',
* 'print' => 'printer.css'));
*
* If you call this more than once, the last one called takes
* precedence as the default style.
*
* @param string $title Name of style (currently ignored, unless
* you call this more than once, in which case, some of the style
* will become alternate (rather than default) styles, and then their
* titles will be used.
*
* @param mixed $css_files Name of CSS file, or hash containing a mapping
* between media types and CSS file names. Use a key of '' (the empty string)
* to set the default CSS for non-specified media. (See above for an example.)
*/
function setDefaultCSS ($title, $css_files) {
if (!is_array($css_files))
$css_files = array('' => $css_files);
// Add to the front of $this->_css
unset($this->_css[$title]);
$this->_css = array_merge(array($title => $css_files), $this->_css);
}
/** Set alternate CSS source for this theme.
*
* @param string $title Name of style.
* @param string $css_files Name of CSS file.
*/
function addAlternateCSS ($title, $css_files) {
if (!is_array($css_files))
$css_files = array('' => $css_files);
$this->_css[$title] = $css_files;
}
/**
* @return string HTML for CSS.
*/
function getCSS () {
$css = array();
$is_alt = false;
foreach ($this->_css as $title => $css_files) {
ksort($css_files); // move $css_files[''] to front.
foreach ($css_files as $media => $css_file) {
if (!empty($this->DUMP_MODE)) {
if ($media == 'print')
$css[] = $this->_CSSlink($title, $css_file, '', $is_alt);
} else {
$css[] = $this->_CSSlink($title, $css_file, $media, $is_alt);
}
if ($is_alt) break;
}
$is_alt = true;
}
return HTML($css);
}
function findTemplate ($name) {
if ($tmp = $this->_findFile("templates/$name.tmpl", 1))
return $this->_path . $tmp;
else {
$f1 = $this->file("templates/$name.tmpl");
//trigger_error("findTemplate($name) pwd: ".getcwd(), E_USER_ERROR);
if (isset($this->_default_theme)) {
$f2 = $this->_default_theme->file("templates/$name.tmpl");
//trigger_error("$f1 nor $f2 found", E_USER_ERROR);
} else
trigger_error("$f1 not found", E_USER_ERROR);
return false;
}
}
var $_MoreHeaders = array();
function addMoreHeaders ($element) {
$this->_MoreHeaders[] = $element;
if (!empty($this->_headers_printed) and $this->_headers_printed) {
trigger_error(_("Some action(page) wanted to add more headers, but they were already printed.")
."\n". $element->asXML(),
E_USER_NOTICE);
}
}
/**
* Singleton. Only called once, by the head template. See the warning above.
*/
function getMoreHeaders () {
// actionpages cannot add headers, because recursive template expansion
// already expanded the head template before.
$this->_headers_printed = 1;
if (empty($this->_MoreHeaders))
return '';
$out = '';
//$out = "<!-- More Headers -->\n";
foreach ($this->_MoreHeaders as $h) {
if (is_object($h))
$out .= printXML($h);
else
$out .= "$h\n";
}
return $out;
}
var $_MoreAttr = array();
// new arg: named elements to be able to remove them. such as DoubleClickEdit for htmldumps
function addMoreAttr ($tag, $name, $element) {
// protect from duplicate attr (body jscript: themes, prefs, ...)
static $_attr_cache = array();
$hash = md5($tag."/".$element);
if (!empty($_attr_cache[$hash])) return;
$_attr_cache[$hash] = 1;
if (empty($this->_MoreAttr) or !is_array($this->_MoreAttr[$tag]))
$this->_MoreAttr[$tag] = array($name => $element);
else
$this->_MoreAttr[$tag][$name] = $element;
}
function getMoreAttr ($tag) {
if (empty($this->_MoreAttr[$tag]))
return '';
$out = '';
foreach ($this->_MoreAttr[$tag] as $name => $element) {
if (is_object($element))
$out .= printXML($element);
else
$out .= "$element";
}
return $out;
}
/**
* Common Initialisations
*/
/**
* The ->load() method replaces the formerly global code in themeinfo.php.
* Without this you would not be able to derive from other themes.
*/
function load() {
// CSS file defines fonts, colors and background images for this
// style. The companion '*-heavy.css' file isn't defined, it's just
// expected to be in the same directory that the base style is in.
// This should result in phpwiki-printer.css being used when
// printing or print-previewing with style "PhpWiki" or "MacOSX" selected.
$this->setDefaultCSS('PhpWiki',
array('' => 'phpwiki.css',
'print' => 'phpwiki-printer.css'));
// This allows one to manually select "Printer" style (when browsing page)
// to see what the printer style looks like.
$this->addAlternateCSS(_("Printer"), 'phpwiki-printer.css', 'print, screen');
$this->addAlternateCSS(_("Top & bottom toolbars"), 'phpwiki-topbottombars.css');
$this->addAlternateCSS(_("Modern"), 'phpwiki-modern.css');
if (isBrowserIE()) {
$this->addMoreHeaders($this->_CSSlink(0,
$this->_findFile('IEFixes.css'),'all'));
$this->addMoreHeaders("\n");
}
/**
* The logo image appears on every page and links to the HomePage.
*/
$this->addImageAlias('logo', WIKI_NAME . 'Logo.png');
$this->addImageAlias('search', 'search.png');
/**
* The Signature image is shown after saving an edited page. If this
* is set to false then the "Thank you for editing..." screen will
* be omitted.
*/
$this->addImageAlias('signature', WIKI_NAME . "Signature.png");
// Uncomment this next line to disable the signature.
//$this->addImageAlias('signature', false);
/*
* Link icons.
*/
$this->setLinkIcon('http');
$this->setLinkIcon('https');
$this->setLinkIcon('ftp');
$this->setLinkIcon('mailto');
$this->setLinkIcon('interwiki');
$this->setLinkIcon('wikiuser');
$this->setLinkIcon('*', 'url');
$this->setButtonSeparator("\n | ");
/**
* WikiWords can automatically be split by inserting spaces between
* the words. The default is to leave WordsSmashedTogetherLikeSo.
*/
$this->setAutosplitWikiWords(false);
/**
* Layout improvement with dangling links for mostly closed wiki's:
* If false, only users with edit permissions will be presented the
* special wikiunknown class with "?" and Tooltip.
* If true (default), any user will see the ?, but will be presented
* the PrintLoginForm on a click.
*/
//$this->setAnonEditUnknownLinks(false);
/*
* You may adjust the formats used for formatting dates and times
* below. (These examples give the default formats.)
* Formats are given as format strings to PHP strftime() function See
* http://www.php.net/manual/en/function.strftime.php for details.
* Do not include the server's zone (%Z), times are converted to the
* user's time zone.
*
* Suggestion for french:
* $this->setDateFormat("%A %e %B %Y");
* $this->setTimeFormat("%H:%M:%S");
* Suggestion for capable php versions, using the server locale:
* $this->setDateFormat("%x");
* $this->setTimeFormat("%X");
*/
//$this->setDateFormat("%B %d, %Y");
//$this->setTimeFormat("%I:%M %p");
/*
* To suppress times in the "Last edited on" messages, give a
* give a second argument of false:
*/
//$this->setDateFormat("%B %d, %Y", false);
/**
* Custom UserPreferences:
* A list of name => _UserPreference class pairs.
* Rationale: Certain themes should be able to extend the predefined list
* of preferences. Display/editing is done in the theme specific userprefs.tmpl
* but storage/sanification/update/... must be extended to the Get/SetPreferences methods.
* See themes/wikilens/themeinfo.php
*/
//$this->customUserPreference();
/**
* Register custom PageList type and define custom PageList classes.
* Rationale: Certain themes should be able to extend the predefined list
* of pagelist types. E.g. certain plugins, like MostPopular might use
* info=pagename,hits,rating
* which displays the rating column whenever the wikilens theme is active.
* See themes/wikilens/themeinfo.php
*/
//$this->addPageListColumn();
} // end of load
/**
* Custom UserPreferences:
* A list of name => _UserPreference class pairs.
* Rationale: Certain themes should be able to extend the predefined list
* of preferences. Display/editing is done in the theme specific userprefs.tmpl
* but storage/sanification/update/... must be extended to the Get/SetPreferences methods.
* These values are just ignored if another theme is used.
*/
function customUserPreferences($array) {
global $customUserPreferenceColumns; // FIXME: really a global?
if (empty($customUserPreferenceColumns)) $customUserPreferenceColumns = array();
//array('wikilens' => new _UserPreference_wikilens());
foreach ($array as $field => $prefobj) {
$customUserPreferenceColumns[$field] = $prefobj;
}
}
/** addPageListColumn(array('rating' => new _PageList_Column_rating('rating', _("Rate"))))
* Register custom PageList types for special themes, like
* 'rating' for wikilens
*/
function addPageListColumn ($array) {
global $customPageListColumns;
if (empty($customPageListColumns)) $customPageListColumns = array();
foreach ($array as $column => $obj) {
$customPageListColumns[$column] = $obj;
}
}
// Works only on action=browse. Patch #970004 by pixels
// Usage: call $WikiTheme->initDoubleClickEdit() from theme init or
// define ENABLE_DOUBLECLICKEDIT
function initDoubleClickEdit() {
if (!$this->HTML_DUMP_SUFFIX)
$this->addMoreAttr('body', 'DoubleClickEdit', HTML::Raw(" ondblclick=\"url = document.URL; url2 = url; if (url.indexOf('?') != -1) url2 = url.slice(0, url.indexOf('?')); if ((url.indexOf('action') == -1) || (url.indexOf('action=browse') != -1)) document.location = url2 + '?action=edit';\""));
}
// Immediate title search results via XMLHTML(HttpRequest)
// by Bitflux GmbH, bitflux.ch. You need to install the livesearch.js seperately.
// Google's or acdropdown is better.
function initLiveSearch() {
//subclasses of Sidebar will init this twice
static $already = 0;
if (!$this->HTML_DUMP_SUFFIX and !$already) {
$this->addMoreAttr('body', 'LiveSearch',
HTML::Raw(" onload=\"liveSearchInit()"));
$this->addMoreHeaders(JavaScript('var liveSearchURI="'
.WikiURL(_("TitleSearch"),false,true).'";'));
$this->addMoreHeaders(JavaScript('', array
('src' => $this->_findData('livesearch.js'))));
$already = 1;
}
}
// Immediate title search results via XMLHttpRequest
// using the shipped moacdropdown js-lib
function initMoAcDropDown() {
//subclasses of Sidebar will init this twice
static $already = 0;
if (!$this->HTML_DUMP_SUFFIX and !$already) {
$dir = $this->_findData('moacdropdown');
// if autocomplete_remote is used: (getobject2 also for calc. the showlist width)
if (DEBUG) {
foreach (array("mobrowser.js","modomevent3.js","modomt.js",
"modomext.js","getobject2.js","xmlextras.js") as $js)
{
$this->addMoreHeaders(JavaScript('', array('src' => "$dir/js/$js")));
}
$this->addMoreHeaders(JavaScript('', array('src' => "$dir/js/acdropdown.js")));
} else {
$this->addMoreHeaders(JavaScript('', array('src' => DATA_PATH . "/themes/default/moacdropdown.js")));
}
//$this->addMoreHeaders($this->_CSSlink(0,
// $this->_findFile('moacdropdown/css/dropdown.css'), 'all'));
$this->addMoreHeaders(HTML::style(" @import url( $dir/css/dropdown.css );\n"));
/*
// for local xmlrpc requests
$xmlrpc_url = deduce_script_name();
//if (1 or DATABASE_TYPE == 'dba')
$xmlrpc_url = DATA_PATH . "/RPC2.php";
if ((DEBUG & _DEBUG_REMOTE) and isset($_GET['start_debug']))
$xmlrpc_url .= ("?start_debug=".$_GET['start_debug']);
$this->addMoreHeaders(JavaScript("var xmlrpc_url = '$xmlrpc_url'"));
*/
$already = 1;
}
}
function calendarLink($date = false) {
return $this->calendarBase() . SUBPAGE_SEPARATOR .
strftime("%Y-%m-%d", $date ? $date : time());
}
function calendarBase() {
static $UserCalPageTitle = false;
global $request;
if (!$UserCalPageTitle)
$UserCalPageTitle = $request->_user->getId() .
SUBPAGE_SEPARATOR . _("Calendar");
if (!$UserCalPageTitle)
$UserCalPageTitle = (BLOG_EMPTY_DEFAULT_PREFIX ? ''
: ($request->_user->getId() . SUBPAGE_SEPARATOR)) . "Blog";
return $UserCalPageTitle;
}
function calendarInit($force = false) {
$dbi = $GLOBALS['request']->getDbh();
// display flat calender dhtml in the sidebar
if ($force or $dbi->isWikiPage($this->calendarBase())) {
$jslang = @$GLOBALS['LANG'];
$this->addMoreHeaders
(
$this->_CSSlink(0,
$this->_findFile('jscalendar/calendar-phpwiki.css'), 'all'));
$this->addMoreHeaders
(JavaScript('',
array('src' => $this->_findData('jscalendar/calendar'.(DEBUG?'':'_stripped').'.js'))));
if (!($langfile = $this->_findData("jscalendar/lang/calendar-$jslang.js")))
$langfile = $this->_findData("jscalendar/lang/calendar-en.js");
$this->addMoreHeaders(JavaScript('',array('src' => $langfile)));
$this->addMoreHeaders
(JavaScript('',
array('src' =>
$this->_findData('jscalendar/calendar-setup'.(DEBUG?'':'_stripped').'.js'))));
// Get existing date entries for the current user
require_once("lib/TextSearchQuery.php");
$iter = $dbi->titleSearch(new TextSearchQuery("^".$this->calendarBase().SUBPAGE_SEPARATOR, true, "auto"));
$existing = array();
while ($page = $iter->next()) {
if ($page->exists())
$existing[] = basename($page->_pagename);
}
if (!empty($existing)) {
$js_exist = '{"'.join('":1,"',$existing).'":1}';
//var SPECIAL_DAYS = {"2004-05-11":1,"2004-05-12":1,"2004-06-01":1}
$this->addMoreHeaders(JavaScript('
// This table holds the existing calender entries for the current user
// calculated from the database
var SPECIAL_DAYS = '.$js_exist.';
// This function returns true if the date exists in SPECIAL_DAYS
function dateExists(date, y, m, d) {
var year = date.getFullYear();
m = m + 1;
m = m < 10 ? "0" + m : m; // integer, 0..11
d = d < 10 ? "0" + d : d; // integer, 1..31
var date = year+"-"+m+"-"+d;
var exists = SPECIAL_DAYS[date];
if (!exists) return false;
else return true;
}
// This is the actual date status handler.
// Note that it receives the date object as well as separate
// values of year, month and date.
function dateStatusFunc(date, y, m, d) {
if (dateExists(date, y, m, d)) return "existing";
else return false;
}'));
}
else {
$this->addMoreHeaders(JavaScript('
function dateStatusFunc(date, y, m, d) { return false;}'));
}
}
}
////////////////////////////////////////////////////////////////
//
// Events
//
////////////////////////////////////////////////////////////////
/* Callback when a new user creates or edits a page */
function CbNewUserEdit (&$request, $userid) {
; // i.e. create homepage with Template/UserPage
}
/* Callback when a new user logs in.
What is new? We only record changes, not logins.
Should we track user actions?
Let's say user without homepage.
*/
function CbNewUserLogin (&$request, $userid) {
; // do nothing
}
/* Callback when a user logs out
*/
function CbUserLogout (&$request, $userid) {
; // do nothing
}
};
/**
* A class representing a clickable "button".
*
* In it's simplest (default) form, a "button" is just a link associated
* with some sort of wiki-action.
*/
class Button extends HtmlElement {
/** Constructor
*
* @param $text string The text for the button.
* @param $url string The url (href) for the button.
* @param $class string The CSS class for the button.
* @param $options array Additional attributes for the <input> tag.
*/
function Button ($text, $url, $class=false, $options=false) {
global $request;
//php5 workaround
if (check_php_version(5)) {
$this->_init('a', array('href' => $url));
} else {
$this->__construct('a', array('href' => $url));
}
if ($class)
$this->setAttr('class', $class);
if ($request->getArg('frame'))
$this->setAttr('target', '_top');
if (!empty($options)) {
foreach ($options as $key => $val)
$this->setAttr($key, $val);
}
// Google honors this
if (in_array(strtolower($text), array('edit','create','diff','pdf'))
and !$request->_user->isAuthenticated())
$this->setAttr('rel', 'nofollow');
$this->pushContent($GLOBALS['WikiTheme']->maybeSplitWikiWord($text));
}
};
/**
* A clickable image button.
*/
class ImageButton extends Button {
/** Constructor
*
* @param $text string The text for the button.
* @param $url string The url (href) for the button.
* @param $class string The CSS class for the button.
* @param $img_url string URL for button's image.
* @param $img_attr array Additional attributes for the <img> tag.
*/
function ImageButton ($text, $url, $class, $img_url, $img_attr=false) {
$this->__construct('a', array('href' => $url));
if ($class)
$this->setAttr('class', $class);
// Google honors this
if (in_array(strtolower($text), array('edit','create','diff','pdf'))
and !$GLOBALS['request']->_user->isAuthenticated())
$this->setAttr('rel', 'nofollow');
if (!is_array($img_attr))
$img_attr = array();
$img_attr['src'] = $img_url;
$img_attr['alt'] = $text;
$img_attr['class'] = 'wiki-button';
$img_attr['border'] = 0;
$this->pushContent(HTML::img($img_attr));
}
};
/**
* A class representing a form <samp>submit</samp> button.
*/
class SubmitButton extends HtmlElement {
/** Constructor
*
* @param $text string The text for the button.
* @param $name string The name of the form field.
* @param $class string The CSS class for the button.
* @param $options array Additional attributes for the <input> tag.
*/
function SubmitButton ($text, $name=false, $class=false, $options=false) {
$this->__construct('input', array('type' => 'submit',
'value' => $text));
if ($name)
$this->setAttr('name', $name);
if ($class)
$this->setAttr('class', $class);
if (!empty($options)) {
foreach ($options as $key => $val)
$this->setAttr($key, $val);
}
}
};
/**
* A class representing an image form <samp>submit</samp> button.
*/
class SubmitImageButton extends SubmitButton {
/** Constructor
*
* @param $text string The text for the button.
* @param $name string The name of the form field.
* @param $class string The CSS class for the button.
* @param $img_url string URL for button's image.
* @param $img_attr array Additional attributes for the <img> tag.
*/
function SubmitImageButton ($text, $name=false, $class=false, $img_url, $img_attr=false) {
$this->__construct('input', array('type' => 'image',
'src' => $img_url,
'value' => $text,
'alt' => $text));
if ($name)
$this->setAttr('name', $name);
if ($class)
$this->setAttr('class', $class);
if (!empty($img_attr)) {
foreach ($img_attr as $key => $val)
$this->setAttr($key, $val);
}
}
};
/**
* A sidebar box with title and body, narrow fixed-width.
* To represent abbrevated content of plugins, links or forms,
* like "Getting Started", "Search", "Sarch Pagename",
* "Login", "Menu", "Recent Changes", "Last comments", "Last Blogs"
* "Calendar"
* ... See http://tikiwiki.org/
*
* Usage:
* sidebar.tmpl:
* $menu = SidebarBox("Menu",HTML::dl(HTML::dt(...))); $menu->format();
* $menu = PluginSidebarBox("RecentChanges",array('limit'=>10)); $menu->format();
*/
class SidebarBox {
function SidebarBox($title, $body) {
require_once('lib/WikiPlugin.php');
$this->title = $title;
$this->body = $body;
}
function format() {
return WikiPlugin::makeBox($this->title, $this->body);
}
}
/**
* A sidebar box for plugins.
* Any plugin may provide a box($args=false, $request=false, $basepage=false)
* method, with the help of WikiPlugin::makeBox()
*/
class PluginSidebarBox extends SidebarBox {
var $_plugin, $_args = false, $_basepage = false;
function PluginSidebarBox($name, $args = false, $basepage = false) {
require_once("lib/WikiPlugin.php");
$loader = new WikiPluginLoader();
$plugin = $loader->getPlugin($name);
if (!$plugin) {
return $loader->_error(sprintf(_("Plugin %s: undefined"),
$name));
}/*
if (!method_exists($plugin, 'box')) {
return $loader->_error(sprintf(_("%s: has no box method"),
get_class($plugin)));
}*/
$this->_plugin =& $plugin;
$this->_args = $args ? $args : array();
$this->_basepage = $basepage;
}
function format($args = false) {
return $this->_plugin->box($args ? array_merge($this->_args, $args) : $this->_args,
$GLOBALS['request'],
$this->_basepage);
}
}
// Various boxes which are no plugins
class RelatedLinksBox extends SidebarBox {
function RelatedLinksBox($title = false, $body = '', $limit = 20) {
global $request;
$this->title = $title ? $title : _("Related Links");
$this->body = HTML($body);
$page = $request->getPage($request->getArg('pagename'));
$revision = $page->getCurrentRevision();
$page_content = $revision->getTransformedContent();
//$cache = &$page->_wikidb->_cache;
$counter = 0;
$sp = HTML::Raw('· ');
foreach ($page_content->getWikiPageLinks() as $link) {
$linkto = $link['linkto'];
if (!$request->_dbi->isWikiPage($linkto)) continue;
$this->body->pushContent($sp, WikiLink($linkto), HTML::br());
$counter++;
if ($limit and $counter > $limit) continue;
}
}
}
class RelatedExternalLinksBox extends SidebarBox {
function RelatedExternalLinksBox($title = false, $body = '', $limit = 20) {
global $request;
$this->title = $title ? $title : _("External Links");
$this->body = HTML($body);
$page = $request->getPage($request->getArg('pagename'));
$cache = &$page->_wikidb->_cache;
$counter = 0;
$sp = HTML::Raw('· ');
foreach ($cache->getWikiPageLinks() as $link) {
$linkto = $link['linkto'];
if ($linkto) {
$this->body->pushContent($sp, WikiLink($linkto), HTML::br());
$counter++;
if ($limit and $counter > $limit) continue;
}
}
}
}
function listAvailableThemes() {
$available_themes = array();
$dir_root = 'themes';
if (defined('PHPWIKI_DIR'))
$dir_root = PHPWIKI_DIR . "/$dir_root";
$dir = dir($dir_root);
if ($dir) {
while($entry = $dir->read()) {
if (is_dir($dir_root.'/'.$entry)
and file_exists($dir_root.'/'.$entry.'/themeinfo.php'))
{
array_push($available_themes, $entry);
}
}
$dir->close();
}
return $available_themes;
}
function listAvailableLanguages() {
$available_languages = array('en');
$dir_root = 'locale';
if (defined('PHPWIKI_DIR'))
$dir_root = PHPWIKI_DIR . "/$dir_root";
if ($dir = dir($dir_root)) {
while($entry = $dir->read()) {
if (is_dir($dir_root."/".$entry) and is_dir($dir_root.'/'.$entry.'/LC_MESSAGES'))
{
array_push($available_languages, $entry);
}
}
$dir->close();
}
return $available_languages;
}
// $Log: Theme.php,v $
// Revision 1.142 2007/07/01 09:36:09 rurban
// themes are now easier derivable classes from other themes.
// removed global code setters, switched to $WikiTheme->load() in main
//
// Revision 1.141 2007/06/02 18:24:30 rurban
// Added accesskeys. Added js stylepath
//
// Revision 1.140 2007/03/10 18:27:20 rurban
// Patch 1677965 by Erwann Penet
//
// Revision 1.138 2007/01/07 18:43:37 rurban
// Remove fatals when no intermediate template was found. Deprecate subclasses of subthemes (blog of Sidebar). Warn about lost _MoreHeaders. $noinit: Do not initialize unnecessary items in default_theme fallback twice. Move over calendarInit from themes/Sidebar/themeinfo.php.
//
// Revision 1.137 2007/01/02 13:19:23 rurban
// add getobject2.js to acdropdown to calculate the sizes. add global xmlrpc_url for local xml requests (interface simplification). stabilize theme and language detection: require magic files there
//
// Revision 1.136 2006/12/06 22:07:31 rurban
// Add new Button argument to override any option.
//
// Revision 1.135 2006/04/17 17:28:21 rurban
// honor getWikiPageLinks change linkto=>relation
//
// Revision 1.134 2006/03/19 16:24:38 rurban
// fix syntax error with patch #1377650
//
// Revision 1.133 2006/03/19 14:24:38 rurban
// sf.net patch #1377650 by Matt Brown: Always prefer legible author name over author_id property
//
// Revision 1.132 2005/07/24 09:51:22 rurban
// guard doubleClickEdit for unittests, add AcDropDown support
//
// Revision 1.131 2005/06/10 06:09:06 rurban
// enable getPref('doubleClickEdit')
//
// Revision 1.130 2005/05/06 16:43:35 rurban
// split long lines
//
// Revision 1.129 2005/05/05 08:57:26 rurban
// support action=revert
//
// Revision 1.128 2005/04/23 11:23:49 rurban
// improve semantics in the setAutosplitWikiWords method: switch to true if no args
//
// Revision 1.127 2005/02/11 14:45:44 rurban
// support ENABLE_LIVESEARCH, enable PDO sessions
//
// Revision 1.126 2005/02/04 11:43:18 rurban
// update comments
//
// Revision 1.125 2005/02/03 05:09:56 rurban
// livesearch.js support
//
// Revision 1.124 2005/01/27 16:28:15 rurban
// especially for Google: nofollow on unauthenticated edit,diff,create,pdf
//
// Revision 1.123 2005/01/25 07:03:02 rurban
// change addMoreAttr() to support named attr, to remove DoubleClickEdit for htmldumps
//
// Revision 1.122 2005/01/21 11:51:22 rurban
// changed (c)
//
// Revision 1.121 2005/01/20 10:14:37 rurban
// rel=nofollow on edit/create page links
//
// Revision 1.120 2004/12/20 13:20:23 rurban
// fix problem described in patch #1088131. SidebarBox may be used before lib/WikiPlugin.php
// is loaded.
//
// Revision 1.119 2004/12/14 21:38:12 rurban
// just aesthetics
//
// Revision 1.118 2004/12/13 14:34:46 rurban
// box parent method exists
//
// Revision 1.117 2004/11/30 17:44:54 rurban
// revisison neutral
//
// Revision 1.116 2004/11/21 11:59:16 rurban
// remove final \n to be ob_cache independent
//
// Revision 1.115 2004/11/17 17:24:02 rurban
// more verbose on fatal template not found
//
// Revision 1.114 2004/11/11 18:31:26 rurban
// add simple backtrace on such general failures to get at least an idea where
//
// Revision 1.113 2004/11/09 17:11:04 rurban
// * revert to the wikidb ref passing. there's no memory abuse there.
// * use new wikidb->_cache->_id_cache[] instead of wikidb->_iwpcache, to effectively
// store page ids with getPageLinks (GleanDescription) of all existing pages, which
// are also needed at the rendering for linkExistingWikiWord().
// pass options to pageiterator.
// use this cache also for _get_pageid()
// This saves about 8 SELECT count per page (num all pagelinks).
// * fix passing of all page fields to the pageiterator.
// * fix overlarge session data which got broken with the latest ACCESS_LOG_SQL changes
//
// Revision 1.112 2004/11/03 16:50:31 rurban
// some new defaults and constants, renamed USE_DOUBLECLICKEDIT to ENABLE_DOUBLECLICKEDIT
//
// Revision 1.111 2004/10/21 20:20:53 rurban
// From patch #970004 "Double clic to edit" by pixels.
//
// Revision 1.110 2004/10/15 11:05:10 rurban
// fix yesterdays premature dumphtml fix for $default_text (thanks John Shen)
//
// Revision 1.109 2004/10/14 21:06:02 rurban
// fix dumphtml with USE_PATH_INFO (again). fix some PageList refs
//
// Revision 1.108 2004/09/26 12:24:02 rurban
// no anchor (PCRE memory), explicit ^ instead
//
// Revision 1.107 2004/06/21 16:22:29 rurban
// add DEFAULT_DUMP_DIR and HTML_DUMP_DIR constants, for easier cmdline dumps,
// fixed dumping buttons locally (images/buttons/),
// support pages arg for dumphtml,
// optional directory arg for dumpserial + dumphtml,
// fix a AllPages warning,
// show dump warnings/errors on DEBUG,
// don't warn just ignore on wikilens pagelist columns, if not loaded.
// RateIt pagelist column is called "rating", not "ratingwidget" (Dan?)
//
// Revision 1.106 2004/06/20 14:42:54 rurban
// various php5 fixes (still broken at blockparser)
//
// Revision 1.105 2004/06/14 11:31:36 rurban
// renamed global $Theme to $WikiTheme (gforge nameclash)
// inherit PageList default options from PageList
// default sortby=pagename
// use options in PageList_Selectable (limit, sortby, ...)
// added action revert, with button at action=diff
// added option regex to WikiAdminSearchReplace
//
// Revision 1.104 2004/06/11 09:07:30 rurban
// support theme-specific LinkIconAttr: front or after or none
//
// Revision 1.103 2004/06/07 22:44:14 rurban
// added simplified chown, setacl actions
//
// Revision 1.102 2004/06/07 18:59:28 rurban
// added Chown link to Owner in statusbar
//
// Revision 1.101 2004/06/03 12:59:40 rurban
// simplify translation
// NS4 wrap=virtual only
//
// Revision 1.100 2004/06/03 10:18:19 rurban
// fix FileUser locking issues, new config ENABLE_PAGEPERM
//
// Revision 1.99 2004/06/01 15:27:59 rurban
// AdminUser only ADMIN_USER not member of Administrators
// some RateIt improvements by dfrankow
// edit_toolbar buttons
//
// Revision 1.98 2004/05/27 17:49:05 rurban
// renamed DB_Session to DbSession (in CVS also)
// added WikiDB->getParam and WikiDB->getAuthParam method to get rid of globals
// remove leading slash in error message
// added force_unlock parameter to File_Passwd (no return on stale locks)
// fixed adodb session AffectedRows
// added FileFinder helpers to unify local filenames and DATA_PATH names
// editpage.php: new edit toolbar javascript on ENABLE_EDIT_TOOLBAR
//
// Revision 1.97 2004/05/18 16:23:39 rurban
// rename split_pagename to SplitPagename
//
// Revision 1.96 2004/05/13 13:48:34 rurban
// doc update for the new 1.3.10 release
//
// Revision 1.94 2004/05/13 11:52:34 rurban
// search also default buttons
//
// Revision 1.93 2004/05/12 10:49:55 rurban
// require_once fix for those libs which are loaded before FileFinder and
// its automatic include_path fix, and where require_once doesn't grok
// dirname(__FILE__) != './lib'
// upgrade fix with PearDB
// navbar.tmpl: remove spaces for IE button alignment
//
// Revision 1.92 2004/05/03 21:57:47 rurban
// locale updates: we previously lost some words because of wrong strings in
// PhotoAlbum, german rewording.
// fixed $_SESSION registering (lost session vars, esp. prefs)
// fixed ending slash in listAvailableLanguages/Themes
//
// Revision 1.91 2004/05/03 11:40:42 rurban
// put listAvailableLanguages() and listAvailableThemes() from SystemInfo and
// UserPreferences into Themes.php
//
// Revision 1.90 2004/05/02 19:12:14 rurban
// fix sf.net bug #945154 Konqueror alt css
//
// Revision 1.89 2004/04/29 21:25:45 rurban
// default theme navbar consistency: linkButtons instead of action buttons
// 3rd makeLinkButtin arg for action support
//
// Revision 1.88 2004/04/19 18:27:45 rurban
// Prevent from some PHP5 warnings (ref args, no :: object init)
// php5 runs now through, just one wrong XmlElement object init missing
// Removed unneccesary UpgradeUser lines
// Changed WikiLink to omit version if current (RecentChanges)
//
// Revision 1.87 2004/04/19 09:13:23 rurban
// new pref: googleLink
//
// Revision 1.86 2004/04/18 01:11:51 rurban
// more numeric pagename fixes.
// fixed action=upload with merge conflict warnings.
// charset changed from constant to global (dynamic utf-8 switching)
//
// Revision 1.85 2004/04/12 13:04:50 rurban
// added auth_create: self-registering Db users
// fixed IMAP auth
// removed rating recommendations
// ziplib reformatting
//
// Revision 1.84 2004/04/10 02:30:49 rurban
// Fixed gettext problem with VIRTUAL_PATH scripts (Windows only probably)
// Fixed "cannot setlocale..." (sf.net problem)
//
// Revision 1.83 2004/04/09 17:49:03 rurban
// Added PhpWiki RssFeed to Sidebar
// sidebar formatting
// some browser dependant fixes (old-browser support)
//
// Revision 1.82 2004/04/06 20:00:10 rurban
// Cleanup of special PageList column types
// Added support of plugin and theme specific Pagelist Types
// Added support for theme specific UserPreferences
// Added session support for ip-based throttling
// sql table schema change: ALTER TABLE session ADD sess_ip CHAR(15);
// Enhanced postgres schema
// Added DB_Session_dba support
//
// Revision 1.81 2004/04/01 15:57:10 rurban
// simplified Sidebar theme: table, not absolute css positioning
// added the new box methods.
// remaining problems: large left margin, how to override _autosplitWikiWords in Template only
//
// Revision 1.80 2004/03/30 02:14:03 rurban
// fixed yet another Prefs bug
// added generic PearDb_iter
// $request->appendValidators no so strict as before
// added some box plugin methods
// PageList commalist for condensed output
//
// Revision 1.79 2004/03/24 19:39:02 rurban
// php5 workaround code (plus some interim debugging code in XmlElement)
// php5 doesn't work yet with the current XmlElement class constructors,
// WikiUserNew does work better than php4.
// rewrote WikiUserNew user upgrading to ease php5 update
// fixed pref handling in WikiUserNew
// added Email Notification
// added simple Email verification
// removed emailVerify userpref subclass: just a email property
// changed pref binary storage layout: numarray => hash of non default values
// print optimize message only if really done.
// forced new cookie policy: delete pref cookies, use only WIKI_ID as plain string.
// prefs should be stored in db or homepage, besides the current session.
//
// Revision 1.78 2004/03/18 22:32:33 rurban
// work to make it php5 compatible
//
// Revision 1.77 2004/03/08 19:30:01 rurban
// fixed Theme->getButtonURL
// AllUsers uses now WikiGroup (also DB User and DB Pref users)
// PageList fix for empty pagenames
//
// Revision 1.76 2004/03/08 18:17:09 rurban
// added more WikiGroup::getMembersOf methods, esp. for special groups
// fixed $LDAP_SET_OPTIONS
// fixed _AuthInfo group methods
//
// Revision 1.75 2004/03/01 09:34:37 rurban
// fixed button path logic: now fallback to default also
//
// Revision 1.74 2004/02/28 21:14:08 rurban
// generally more PHPDOC docs
// see http://xarch.tu-graz.ac.at/home/rurban/phpwiki/xref/
// fxied WikiUserNew pref handling: empty theme not stored, save only
// changed prefs, sql prefs improved, fixed password update,
// removed REPLACE sql (dangerous)
// moved gettext init after the locale was guessed
// + some minor changes
//
// Revision 1.73 2004/02/26 03:22:05 rurban
// also copy css and images with XHTML Dump
//
// Revision 1.72 2004/02/26 02:25:53 rurban
// fix empty and #-anchored links in XHTML Dumps
//
// Revision 1.71 2004/02/15 21:34:37 rurban
// PageList enhanced and improved.
// fixed new WikiAdmin... plugins
// editpage, Theme with exp. htmlarea framework
// (htmlarea yet committed, this is really questionable)
// WikiUser... code with better session handling for prefs
// enhanced UserPreferences (again)
// RecentChanges for show_deleted: how should pages be deleted then?
//
// Revision 1.70 2004/01/26 09:17:48 rurban
// * changed stored pref representation as before.
// the array of objects is 1) bigger and 2)
// less portable. If we would import packed pref
// objects and the object definition was changed, PHP would fail.
// This doesn't happen with an simple array of non-default values.
// * use $prefs->retrieve and $prefs->store methods, where retrieve
// understands the interim format of array of objects also.
// * simplified $prefs->get() and fixed $prefs->set()
// * added $user->_userid and class '_WikiUser' portability functions
// * fixed $user object ->_level upgrading, mostly using sessions.
// this fixes yesterdays problems with loosing authorization level.
// * fixed WikiUserNew::checkPass to return the _level
// * fixed WikiUserNew::isSignedIn
// * added explodePageList to class PageList, support sortby arg
// * fixed UserPreferences for WikiUserNew
// * fixed WikiPlugin for empty defaults array
// * UnfoldSubpages: added pagename arg, renamed pages arg,
// removed sort arg, support sortby arg
//
// Revision 1.69 2003/12/05 01:32:28 carstenklapp
// New feature: Easier to run multiple wiks off of one set of code. Name
// your logo and signature image files "YourWikiNameLogo.png" and
// "YourWikiNameSignature.png" and put them all into
// themes/default/images. YourWikiName should match what is defined as
// WIKI_NAME in index.php. In case the image is not found, the default
// shipped with PhpWiki will be used.
//
// Revision 1.68 2003/03/04 01:53:30 dairiki
// Inconsequential decrufting.
//
// Revision 1.67 2003/02/26 03:40:22 dairiki
// New action=create. Essentially the same as action=edit, except that if the
// page already exists, it falls back to action=browse.
//
// This is for use in the "question mark" links for unknown wiki words
// to avoid problems and confusion when following links from stale pages.
// (If the "unknown page" has been created in the interim, the user probably
// wants to view the page before editing it.)
//
// Revision 1.66 2003/02/26 00:10:26 dairiki
// More/better/different checks for bad page names.
//
// Revision 1.65 2003/02/24 22:41:57 dairiki
// Fix stupid typo.
//
// Revision 1.64 2003/02/24 22:06:14 dairiki
// Attempts to fix auto-selection of printer CSS when printing.
// See new comments lib/Theme.php for more details.
// Also see SF patch #669563.
//
// Revision 1.63 2003/02/23 03:37:05 dairiki
// Stupid typo/bug fix.
//
// Revision 1.62 2003/02/21 04:14:52 dairiki
// New WikiLink type 'if_known'. This gives linkified name if page
// exists, otherwise, just plain text.
//
// Revision 1.61 2003/02/18 21:52:05 dairiki
// Fix so that one can still link to wiki pages with # in their names.
// (This was made difficult by the introduction of named tags, since
// '[Page #1]' is now a link to anchor '1' in page 'Page'.
//
// Now the ~ escape for page names should work: [Page ~#1].
//
// Revision 1.60 2003/02/15 01:59:47 dairiki
// Theme::getCSS(): Add Default-Style HTTP(-eqiv) header in attempt
// to fix default stylesheet selection on some browsers.
// For details on the Default-Style header, see:
// http://home.dairiki.org/docs/html4/present/styles.html#h-14.3.2
//
// Revision 1.59 2003/01/04 22:30:16 carstenklapp
// New: display a "Never edited." message instead of an invalid epoch date.
//
// (c-file-style: "gnu")
// Local Variables:
// mode: php
// tab-width: 8
// c-basic-offset: 4
// c-hanging-comment-ender-p: nil
// indent-tabs-mode: nil
// End:
?>
|