the bulk of theme engine 2.0; it's still rough, but it works

git-svn-id: file:///home/shish/svn/shimmie2/trunk@201 7f39781d-f577-437e-ae19-be835c7a54ca
This commit is contained in:
shish 2007-06-30 01:19:11 +00:00
parent d06f0ef30f
commit a625fcd787
58 changed files with 1198 additions and 891 deletions

View file

@ -8,8 +8,11 @@
*/
class AdminUtils extends Extension {
var $theme;
// event handler {{{
public function receive_event($event) {
if(is_null($this->theme)) $this->theme = get_theme_object("admin_utils", "AdminUtilsTheme");
if(is_a($event, 'PageRequestEvent') && ($event->page == "admin_utils")) {
global $user;
if($user->is_admin()) {
@ -29,7 +32,7 @@ class AdminUtils extends Extension {
if(is_a($event, 'AdminBuildingEvent')) {
global $page;
$page->add_main_block(new Block("Misc Admin Tools", $this->build_form()));
$this->theme->display_form($page);
}
}
// }}}
@ -50,17 +53,6 @@ class AdminUtils extends Extension {
}
}
// }}}
// admin page HTML {{{
private function build_form() {
$html = "
<p><form action='".make_link("admin_utils")."' method='POST'>
<input type='hidden' name='action' value='lowercase all tags'>
<input type='submit' value='Lowercase All Tags'>
</form>
";
return $html;
}
// }}}
}
add_event_listener(new AdminUtils());
?>

View file

@ -0,0 +1,14 @@
<?php
class AdminUtilsTheme extends Themelet {
public function display_form() {
$html = "
<p><form action='".make_link("admin_utils")."' method='POST'>
<input type='hidden' name='action' value='lowercase all tags'>
<input type='submit' value='Lowercase All Tags'>
</form>
";
$page->add_block(new Block("Misc Admin Tools", $html));
}
}
?>

View file

@ -5,7 +5,7 @@ class AutoComplete extends Extension {
public function receive_event($event) {
if(is_a($event, 'PageRequestEvent') && ($event->page == "index" || $event->page == "view")) {
global $page;
$page->add_side_block(new Block(null, $this->build_autocomplete_script()));
$page->add_header("<script>autocomplete_url='".html_escape(make_link("autocomplete"))."';</script>");
}
if(is_a($event, 'PageRequestEvent') && ($event->page == "autocomplete")) {
global $page;
@ -22,52 +22,6 @@ class AutoComplete extends Extension {
return implode("\n", $tags);
}
// }}}
// html {{{
private function build_autocomplete_script() {
global $database;
$ac_url = html_escape(make_link("autocomplete"));
return <<<EOD
<script>
//completion_cache = new array();
input = byId("search_input");
output = byId("search_completions");
function get_cached_completions(start) {
// if(completion_cache[start]) {
// return completion_cache[start];
// }
// else {
return null;
// }
}
function get_completions(start) {
cached = get_cached_completions(start);
if(cached) {
output.innerHTML = cached;
}
else {
ajaxRequest("$ac_url/"+start, function(data) {set_completions(start, data);});
}
}
function set_completions(start, data) {
// completion_cache[start] = data;
output.innerHTML = data;
}
input.onkeyup = function() {
if(input.value.length < 3) {
output.innerHTML = "";
}
else {
get_completions(input.value);
}
};
</script>
EOD;
}
// }}}
}
add_event_listener(new AutoComplete());
?>

View file

@ -0,0 +1,98 @@
// addEvent(window, "load", function() {
// initAjax("searchBox", "search_completions");
// initAjax("tagBox", "upload_completions");
// });
function endWord(sentance) {
words = sentance.split(" ");
return words[words.length-1];
}
var resultCache = new Array();
resultCache[""] = new Array();
function complete(boxname, text) {
box = byId(boxname);
words = box.value.split(" ");
box.value = "";
for(n=0; n<words.length-1; n++) {
box.value += words[n]+" ";
}
box.value += text+" ";
box.focus();
return false;
}
function fillCompletionZone(boxname, areaname, results) {
byId(areaname).innerHTML = "";
for(i=0; i<results.length; i++) {
byId(areaname).innerHTML += "<br><a href=\"#\" onclick=\"complete('"+boxname+"', '"+results[i]+"');\">"+results[i]+"</a>";
}
}
function initAjax(boxname, areaname) {
var box = byId(boxname);
if(!box) return;
addEvent(
box,
"keyup",
function f() {
starter = endWord(box.value);
if(resultCache[starter]) {
fillCompletionZone(boxname, areaname, resultCache[starter]);
}
else {
ajaxRequest(
"ajax.php?start="+starter,
function g(text) {
resultCache[starter] = text.split("\n");
fillCompletionZone(boxname, areaname, resultCache[starter]);
}
);
}
},
false
);
}
//completion_cache = new array();
input = byId("search_input");
output = byId("search_completions");
function get_cached_completions(start) {
// if(completion_cache[start]) {
// return completion_cache[start];
// }
// else {
return null;
// }
}
function get_completions(start) {
cached = get_cached_completions(start);
if(cached) {
output.innerHTML = cached;
}
else {
ajaxRequest(autocomplete_url+"/"+start, function(data) {set_completions(start, data);});
}
}
function set_completions(start, data) {
// completion_cache[start] = data;
output.innerHTML = data;
}
if(input) {
input.onkeyup = function() {
if(input.value.length < 3) {
output.innerHTML = "";
}
else {
get_completions(input.value);
}
};
}

View file

@ -0,0 +1,5 @@
<?php
/*
* autocomplete has no HTML parts
*/
?>

View file

@ -31,7 +31,7 @@ class Home extends Extension {
$sb->add_longtext_option("home_links", "<br>");
$sb->add_choice_option("home_counter", $counters, "<br>Counter: ");
$sb->add_label("<br>Note: page accessed via /home");
$event->panel->add_main_block($sb);
$event->panel->add_block($sb);
}
if(is_a($event, 'ConfigSaveEvent'))
{

View file

@ -10,13 +10,12 @@ class LinkImage extends Extension {
global $config;
$data_href = $config->get_string("data_href");
$page->add_header("<link rel='stylesheet' href='$data_href/ext/link_image/_style.css' type='text/css'>",0);
$page->add_main_block(new Block("Link to Image", $this->get_html($event->image)));
$page->add_block(new Block("Link to Image", $this->get_html($event->image)));
}
if(is_a($event, 'SetupBuildingEvent')) {
$sb = new SetupBlock("Link to Image");
//$sb->add_label("Text link format: ");
$sb->add_text_option("ext_link-img_text-link_format","Text Link Format:");
$event->panel->add_main_block($sb);
$event->panel->add_block($sb);
}
if(is_a($event, 'ConfigSaveEvent')) {
$event->config->set_string_from_post("ext_link-img_text-link_format");

View file

@ -1,7 +1,11 @@
<?php
class Notes extends Extension {
var $theme;
public function receive_event($event) {
if(is_null($this->theme)) $this->theme = get_theme_object("notes", "NotesTheme");
if(is_a($event, 'InitExtEvent')) {
global $config;
if($config->get_int("ext_notes_version") < 1) {
@ -11,42 +15,32 @@ class Notes extends Extension {
if(is_a($event, 'DisplayingImageEvent')) {
global $page;
$page->add_main_block(new Block(null, $this->make_notes($event->image->id)));
global $database;
$notes = $database->db->GetAll("SELECT * FROM image_notes WHERE image_id = ?", array($event->image->id));
$this->theme->display_notes($page, $notes);
}
}
protected function install() {
global $database;
global $config;
$database->Execute("CREATE TABLE `image_notes` (
`id` int(11) NOT NULL auto_increment,
`image_id` int(11) NOT NULL,
`user_id` int(11) NOT NULL,
`owner_ip` char(15) NOT NULL,
`created_at` datetime NOT NULL,
`updated_at` datetime NOT NULL,
`version` int(11) DEFAULT 1 NOT NULL,
`is_active` enum('Y', 'N') DEFAULT 'Y' NOT NULL,
`x` int(11) NOT NULL,
`y` int(11) NOT NULL,
`w` int(11) NOT NULL,
`h` int(11) NOT NULL,
`body` text NOT NULL,
PRIMARY KEY (`id`)
$database->Execute("CREATE TABLE image_notes (
id int(11) NOT NULL auto_increment PRIMARY KEY,
image_id int(11) NOT NULL,
user_id int(11) NOT NULL,
owner_ip char(15) NOT NULL,
created_at datetime NOT NULL,
updated_at datetime NOT NULL,
version int(11) DEFAULT 1 NOT NULL,
is_active enum('Y', 'N') DEFAULT 'Y' NOT NULL,
x int(11) NOT NULL,
y int(11) NOT NULL,
w int(11) NOT NULL,
h int(11) NOT NULL,
body text NOT NULL
)");
$config->set_int("ext_notes_version", 1);
}
private function make_notes($image_id) {
global $database;
$notes = $database->db->GetAll("SELECT * FROM image_notes WHERE image_id = ?", array($image_id));
return <<<EOD
<script type="text/javascript">
img = byId("main_image");
</script>
EOD;
}
}
add_event_listener(new Notes());
?>

13
contrib/notes/theme.php Normal file
View file

@ -0,0 +1,13 @@
<?php
class NotesTheme extends Themelet {
public function display_notes($page, $notes) {
$html = <<<EOD
<script type="text/javascript">
img = byId("main_image");
</script>
EOD;
$page->add_block(new Block(null, $html));
}
}
?>

View file

@ -30,7 +30,7 @@ class Ratings extends Extension {
$sb->add_label("<br>Show ");
$sb->add_int_option("comment_count", 0, 100);
$sb->add_label(" recent comments on the index");
$event->panel->add_main_block($sb);
$event->panel->add_block($sb);
}
if(is_a($event, 'ConfigSaveEvent')) {
$event->config->set_bool("comment_anon", $_POST['comment_anon']);

View file

@ -0,0 +1,5 @@
<?php
/*
* RSS has no HTML parts
*/
?>

View file

@ -21,7 +21,7 @@ class SiteDescription extends Extension {
if(is_a($event, 'SetupBuildingEvent')) {
$sb = new SetupBlock("Site Description");
$sb->add_longtext_option("site_description");
$event->panel->add_main_block($sb);
$event->panel->add_block($sb);
}
if(is_a($event, 'ConfigSaveEvent')) {
$event->config->set_string_from_post("site_description");

View file

@ -0,0 +1,5 @@
<?php
/*
* site description has no HTML parts
*/
?>

View file

@ -63,7 +63,7 @@ class Wiki extends Extension {
if(is_a($event, 'PageRequestEvent') && ($event->page == "wiki")) {
global $page;
$page->add_side_block(new NavBlock());
$page->add_block(new NavBlock());
if(is_null($event->get_arg(0)) || strlen(trim($event->get_arg(0))) == 0) {
$title = "Index";
@ -101,7 +101,7 @@ class Wiki extends Extension {
global $page;
$page->set_title("Denied");
$page->set_heading("Denied");
$page->add_side_block(new NavBlock());
$page->add_block(new NavBlock());
$page->add_main_block(new Block("Denied", "You do not have permission to edit this page"));
}
}
@ -137,7 +137,7 @@ class Wiki extends Extension {
$sb = new SetupBlock("Wiki");
$sb->add_bool_option("wiki_edit_anon", "Allow anonymous edits: ");
$sb->add_bool_option("wiki_edit_user", "<br>Allow user edits: ");
$event->panel->add_main_block($sb);
$event->panel->add_block($sb);
}
if(is_a($event, 'ConfigSaveEvent')) {
$event->config->set_bool_from_post("wiki_edit_anon");

View file

@ -2,10 +2,14 @@
class Block {
var $header;
var $body;
var $section;
var $position;
public function Block($header, $body) {
public function Block($header, $body, $section="main", $position=50) {
$this->header = $header;
$this->body = $body;
$this->section = $section;
$this->position = $position;
}
}
?>

View file

@ -14,10 +14,12 @@
class PageRequestEvent extends Event {
var $page;
var $args;
var $page_object;
public function PageRequestEvent($page, $args) {
public function PageRequestEvent($page, $args, $page_object) {
$this->page = $page;
$this->args = $args;
$this->page_object = $page_object;
}
public function get_arg($n) {

View file

@ -17,8 +17,8 @@ class AdminPage extends Extension {
global $page;
$page->set_title("Error");
$page->set_heading("Error");
$page->add_side_block(new NavBlock(), 0);
$page->add_main_block(new Block("Permission Denied", "This page is for admins only"), 0);
$page->add_block(new NavBlock());
$page->add_block(new Block("Permission Denied", "This page is for admins only"));
}
else {
if($event->get_arg(0) == "delete_image") {
@ -44,7 +44,7 @@ class AdminPage extends Extension {
global $user;
if($user->is_admin()) {
global $page;
$page->add_side_block(new Block("Admin", $this->build_del_block($event->image->id)));
$page->add_block(new Block("Admin", $this->build_del_block($event->image->id), "left"));
}
}
@ -75,7 +75,7 @@ class AdminPage extends Extension {
global $page;
$page->set_title("Admin Tools");
$page->set_heading("Admin Tools");
$page->add_side_block(new NavBlock(), 0);
$page->add_block(new NavBlock());
}
// }}}
}

View file

@ -47,7 +47,7 @@ class ImageIO extends Extension {
$sb->add_shorthand_int_option("thumb_gd_mem_limit", "<br>Max GD memory use: ");
$event->panel->add_main_block($sb);
$event->panel->add_block($sb);
}
if(is_a($event, 'ConfigSaveEvent')) {
$event->config->set_string_from_post("thumb_engine");
@ -157,7 +157,7 @@ class ImageIO extends Extension {
*/
$existing = $database->get_image_by_hash($image->hash);
if(!is_null($existing)) {
$page->add_main_block(new Block("Error uploading {$image->filename}",
$page->add_block(new Block("Error uploading {$image->filename}",
"Image <a href='".make_link("post/view/{$existing->id}")."'>{$existing->id}</a> ".
"already has hash {$image->hash}:<p>".
build_thumb_html($existing)));
@ -178,7 +178,7 @@ class ImageIO extends Extension {
* insert the image info into the database
*/
if(!copy($image->temp_filename, $image->get_image_filename())) {
$page->add_main_block(new Block("Error uploading {$image->filename}",
$page->add_block(new Block("Error uploading {$image->filename}",
"The image couldn't be moved from the temporary area to the
main data store -- is the web server allowed to write to '".
($image->get_image_filename())."'?"));
@ -188,7 +188,7 @@ class ImageIO extends Extension {
chmod($image->get_image_filename(), 0644);
if(!$this->make_thumb($image->get_image_filename(), $image->get_thumb_filename())) {
$page->add_main_block(new Block("Error uploading {$image->filename}",
$page->add_block(new Block("Error uploading {$image->filename}",
"The image thumbnail couldn't be generated -- is the web
server allowed to write to '".($image->get_thumb_filename())."'?"));
send_event(new ImageDeletionEvent($image->id));
@ -240,8 +240,8 @@ class ImageIO extends Extension {
else {
$page->set_title("Not Found");
$page->set_heading("Not Found");
$page->add_side_block(new Block("Navigation", "<a href='".index."'>Index</a>"), 0);
$page->add_main_block(new Block("Image not in database",
$page->add_block(new Block("Navigation", "<a href='".index."'>Index</a>", "left", 0));
$page->add_block(new Block("Image not in database",
"The requested image was not found in the database"));
}
}

View file

@ -51,18 +51,19 @@ class Index extends Extension {
$page->set_title($page_title);
$page->set_heading($page_title);
$page->add_side_block(new Block("Navigation", $this->build_navigation($page_number, $total_pages, $search_terms)), 0);
$page->add_block(new Block("Navigation", $this->build_navigation($page_number, $total_pages, $search_terms), "left", 0));
if(count($images) > 0) {
$page->add_main_block(new Block("Images", $this->build_table($images, $query)), 10);
$page->add_main_block(new Paginator("index", $query, $page_number, $total_pages), 90);
$page->add_block(new Block("Images", $this->build_table($images, $query), "main", 10));
$page->add_block(new Paginator("index", $query, $page_number, $total_pages));
}
else {
$page->add_main_block(new Block("No Images Found", "No images were found to match the search criteria"));
$page->add_block(new Block("No Images Found", "No images were found to match the search criteria"));
}
}
if(is_a($event, 'SetupBuildingEvent')) {
$sb = new SetupBlock("Index Options");
$sb->position = 20;
$sb->add_label("Index table size ");
$sb->add_int_option("index_width");
@ -72,7 +73,7 @@ class Index extends Extension {
$sb->add_text_option("image_tip", "<br>Image tooltip ");
$event->panel->add_main_block($sb, 20);
$event->panel->add_block($sb);
}
if(is_a($event, 'ConfigSaveEvent')) {
$event->config->set_int_from_post("index_width");

View file

@ -19,7 +19,12 @@ class SetupBuildingEvent extends Event {
/* SetupPanel {{{
*
*/
class SetupPanel extends Page {
class SetupPanel {
var $blocks = array();
public function add_block($block) {
$this->blocks[] = $block;
}
}
// }}}
/* SetupBlock {{{
@ -31,6 +36,8 @@ class SetupBlock extends Block {
public function SetupBlock($title) {
$this->header = $title;
$this->section = "main";
$this->position = 50;
}
public function add_label($text) {
@ -118,8 +125,8 @@ class Setup extends Extension {
global $page;
$page->set_title("Error");
$page->set_heading("Error");
$page->add_side_block(new NavBlock(), 0);
$page->add_main_block(new Block("Permission Denied", "This page is for admins only"), 0);
$page->add_block(new NavBlock());
$page->add_block(new Block("Permission Denied", "This page is for admins only"));
}
else {
if($event->get_arg(0) == "save") {
@ -147,6 +154,7 @@ class Setup extends Extension {
}
$sb = new SetupBlock("General");
$sb->position = 0;
$sb->add_text_option("title", "Site title: ");
$sb->add_text_option("front_page", "<br>Front page: ");
$sb->add_text_option("base_href", "<br>Base URL: ");
@ -155,7 +163,7 @@ class Setup extends Extension {
$sb->add_choice_option("theme", $themes, "<br>Theme: ");
// $sb->add_int_option("anon_id", "<br>Anonymous ID: "); // FIXME: create advanced options page
$sb->add_hidden_option("anon_id");
$event->panel->add_main_block($sb, 0);
$event->panel->add_block($sb);
}
if(is_a($event, 'ConfigSaveEvent')) {
$event->config->set_string_from_post("title");
@ -179,7 +187,7 @@ class Setup extends Extension {
$setupblock_html1 = "";
$setupblock_html2 = "";
ksort($panel->mainblocks);
usort($panel->blocks, "blockcmp");
/*
$flip = true;
@ -198,7 +206,7 @@ class Setup extends Extension {
*/
$len1 = 0;
$len2 = 0;
foreach($panel->mainblocks as $block) {
foreach($panel->blocks as $block) {
if(is_a($block, 'SetupBlock')) {
$html = $this->sb_to_html($block);
$len = count(explode("<br>", $html));
@ -223,8 +231,8 @@ class Setup extends Extension {
global $page;
$page->set_title("Shimmie Setup");
$page->set_heading("Shimmie Setup");
$page->add_side_block(new Block("Navigation", $this->build_navigation()), 0);
$page->add_main_block(new Block("Setup", $table));
$page->add_block(new Block("Navigation", $this->build_navigation(), "left", 0));
$page->add_block(new Block("Setup", $table));
}
private function build_navigation() {

View file

@ -17,8 +17,8 @@ class TagEdit extends Extension {
else {
$page->set_title("Tag Edit Denied");
$page->set_heading("Tag Edit Denied");
$page->add_side_block(new NavBlock());
$page->add_main_block(new Block("Error", "Anonymous tag editing is disabled"));
$page->add_block(new NavBlock());
$page->add_block(new Block("Error", "Anonymous tag editing is disabled"));
}
}
else if($event->get_arg(0) == "replace") {
@ -34,7 +34,7 @@ class TagEdit extends Extension {
if(is_a($event, 'DisplayingImageEvent')) {
global $page;
$page->add_main_block(new Block(null, $this->build_tag_editor($event->image)), 5);
$page->add_block(new Block(null, $this->build_tag_editor($event->image)), "main", 5);
}
if(is_a($event, 'TagSetEvent')) {
@ -49,7 +49,7 @@ class TagEdit extends Extension {
if(is_a($event, 'AdminBuildingEvent')) {
global $page;
$page->add_main_block(new Block("Mass Tag Edit", $this->build_mass_tag_edit()));
$page->add_block(new Block("Mass Tag Edit", $this->build_mass_tag_edit()));
}
// When an alias is added, oldtag becomes inaccessable
@ -60,7 +60,7 @@ class TagEdit extends Extension {
if(is_a($event, 'SetupBuildingEvent')) {
$sb = new SetupBlock("Tag Editing");
$sb->add_bool_option("tag_edit_anon", "Allow anonymous editing: ");
$event->panel->add_main_block($sb);
$event->panel->add_block($sb);
}
if(is_a($event, 'ConfigSaveEvent')) {
$event->config->set_bool_from_post("tag_edit_anon");

View file

@ -30,8 +30,8 @@ class UserPage extends Extension {
else {
$page->set_title("Login");
$page->set_heading("Login");
$page->add_side_block(new NavBlock());
$page->add_main_block(new Block("Login There",
$page->add_block(new NavBlock());
$page->add_block(new Block("Login There",
"There should be a login box to the left"));
}
}
@ -61,10 +61,10 @@ class UserPage extends Extension {
global $page;
if($user->is_anonymous()) {
$page->add_side_block(new Block("Login", $this->build_login_block()), 90);
$page->add_block(new Block("Login", $this->build_login_block(), "left", 90));
}
else {
$page->add_side_block(new Block("User Links", $this->build_links_block()), 90);
$page->add_block(new Block("User Links", $this->build_links_block(), "left", 90));
}
}
@ -72,7 +72,7 @@ class UserPage extends Extension {
$sb = new SetupBlock("User Options");
$sb->add_bool_option("login_signup_enabled", "Allow new signups: ");
$sb->add_longtext_option("login_tac", "<br>Terms &amp; Conditions:<br>");
$event->panel->add_main_block($sb);
$event->panel->add_block($sb);
}
if(is_a($event, 'ConfigSaveEvent')) {
$event->config->set_bool_from_post("login_signup_enabled");
@ -81,7 +81,7 @@ class UserPage extends Extension {
if(is_a($event, 'UserBlockBuildingEvent')) {
$event->add_link("User Config", make_link("user"));
$event->add_link("Log Out", make_link("user/logout"));
$event->add_link("Log Out", make_link("user/logout"), 99);
}
}
// }}}
@ -116,8 +116,8 @@ class UserPage extends Extension {
else {
$page->set_title("Permission Denied");
$page->set_heading("Permission Denied");
$page->add_side_block(new NavBlock(), 0);
$page->add_main_block(new Block("Error", "No user with those details was found"));
$page->add_block(new NavBlock());
$page->add_block(new Block("Error", "No user with those details was found"));
}
}
@ -129,8 +129,8 @@ class UserPage extends Extension {
if(!$config->get_bool("login_signup_enabled")) {
$page->set_title("Signups Disabled");
$page->set_heading("Signups Disabled");
$page->add_side_block(new NavBlock());
$page->add_main_block(new Block("Signups Disabled",
$page->add_block(new NavBlock());
$page->add_block(new Block("Signups Disabled",
"The board admin has disabled the ability to create new accounts~"));
}
else if(isset($_POST['name']) && isset($_POST['pass1']) && isset($_POST['pass2'])) {
@ -140,15 +140,15 @@ class UserPage extends Extension {
$page->set_title("Error");
$page->set_heading("Error");
$page->add_side_block(new NavBlock());
$page->add_block(new NavBlock());
if(strlen($name) < 1) {
$page->add_main_block(new Block("Error", "Username must be at least 1 character"));
$page->add_block(new Block("Error", "Username must be at least 1 character"));
}
else if($pass1 != $pass2) {
$page->add_main_block(new Block("Error", "Passwords don't match"));
$page->add_block(new Block("Error", "Passwords don't match"));
}
else if($database->db->GetRow("SELECT * FROM users WHERE name = ?", array($name))) {
$page->add_main_block(new Block("Error", "That username is already taken"));
$page->add_block(new Block("Error", "That username is already taken"));
}
else {
$addr = $_SERVER['REMOTE_ADDR'];
@ -171,12 +171,12 @@ class UserPage extends Extension {
else {
$page->set_title("Create Account");
$page->set_heading("Create Account");
$page->add_side_block(new NavBlock());
$page->add_main_block(new Block("Signup", $this->build_signup_form()));
$page->add_block(new NavBlock());
$page->add_block(new Block("Signup", $this->build_signup_form()));
}
}
//}}}
// Things do ne *to* the user {{{
// Things done *to* the user {{{
private function change_password_wrapper() {
global $user;
global $page;
@ -184,9 +184,9 @@ class UserPage extends Extension {
$page->set_title("Error");
$page->set_heading("Error");
$page->add_side_block(new NavBlock());
$page->add_block(new NavBlock());
if($user->is_anonymous()) {
$page->add_main_block(new Block("Error", "You aren't logged in"));
$page->add_block(new Block("Error", "You aren't logged in"));
}
else if(isset($_POST['id']) && isset($_POST['name']) &&
isset($_POST['pass1']) && isset($_POST['pass2'])) {
@ -196,11 +196,11 @@ class UserPage extends Extension {
$pass2 = $_POST['pass2'];
if((!$user->is_admin()) && ($name != $user->name)) {
$page->add_main_block(new Block("Error",
$page->add_block(new Block("Error",
"You need to be an admin to change other people's passwords"));
}
else if($pass1 != $pass2) {
$page->add_main_block(new Block("Error", "Passwords don't match"));
$page->add_block(new Block("Error", "Passwords don't match"));
}
else {
global $config;
@ -236,12 +236,12 @@ class UserPage extends Extension {
$page->set_title("Error");
$page->set_heading("Error");
$page->add_side_block(new NavBlock());
$page->add_block(new NavBlock());
if(!$user->is_admin()) {
$page->add_main_block(new Block("Not Admin", "Only admins can edit accounts"));
$page->add_block(new Block("Not Admin", "Only admins can edit accounts"));
}
else if(!isset($_POST['id']) || !is_numeric($_POST['id'])) {
$page->add_main_block(new Block("No ID Specified",
$page->add_block(new Block("No ID Specified",
"You need to specify the account number to edit"));
}
else {
@ -293,24 +293,24 @@ class UserPage extends Extension {
if(!is_null($duser)) {
$page->set_title("{$duser->name}'s Page");
$page->set_heading("{$duser->name}'s Page");
$page->add_side_block(new NavBlock(), 0);
$page->add_main_block(new Block("Stats", $this->build_stats($duser)));
$page->add_block(new NavBlock());
$page->add_block(new Block("Stats", $this->build_stats($duser)));
if(!$user->is_anonymous()) {
if($user->id == $duser->id || $user->is_admin()) {
$page->add_main_block(new Block("Options", $this->build_options($duser)));
$page->add_block(new Block("Options", $this->build_options($duser), "main", 0));
}
if($user->is_admin()) {
$page->add_main_block(new Block("More Options", $this->build_more_options($duser)));
$page->add_main_block(new Block("IP List", $this->build_ip_list($duser)));
$page->add_block(new Block("More Options", $this->build_more_options($duser)));
$page->add_block(new Block("IP List", $this->build_ip_list($duser)));
}
}
}
else {
$page->set_title("No Such User");
$page->set_heading("No Such User");
$page->add_side_block(new NavBlock(), 0);
$page->add_main_block(new Block("No User By That ID",
$page->add_block(new NavBlock());
$page->add_block(new Block("No User By That ID",
"If you typed the ID by hand, try again; if you came from a link on this ".
"site, it might be bug report time..."));
}
@ -423,6 +423,7 @@ class UserPage extends Extension {
$h_name = html_escape($user->name);
$html = "Logged in as $h_name<br>";
ksort($ubbe->parts);
$html .= join("\n<br/>", $ubbe->parts);
return $html;

View file

@ -16,9 +16,9 @@ class ViewImage extends Extension {
global $page;
$page->set_title("Image not found");
$page->set_heading("Image not found");
$page->add_side_block(new NavBlock(), 0);
$page->add_main_block(new Block("Image not found",
"No image in the database has the ID #$image_id"), 0);
$page->add_block(new NavBlock());
$page->add_block(new Block("Image not found",
"No image in the database has the ID #$image_id"));
}
}
@ -28,17 +28,18 @@ class ViewImage extends Extension {
global $page;
$page->set_title("Image {$image->id}: ".$image->get_tag_list());
$page->set_heading($image->get_tag_list());
$page->add_side_block(new Block("Navigation", $this->build_navigation($image->id)), 0);
$page->add_main_block(new Block("Image", $this->build_image_view($image)), 0);
$page->add_main_block(new Block(null, $this->build_info($image)), 10);
$page->add_block(new Block("Navigation", $this->build_navigation($image->id), "left", 0));
$page->add_block(new Block("Image", $this->build_image_view($image), "main", 0));
$page->add_block(new Block(null, $this->build_info($image), "main", 10));
}
if(is_a($event, 'SetupBuildingEvent')) {
$sb = new SetupBlock("View Options");
$sb->position = 30;
$sb->add_text_option("image_ilink", "Long link ");
$sb->add_text_option("image_slink", "<br>Short link ");
$sb->add_text_option("image_tlink", "<br>Thumbnail link ");
$event->panel->add_main_block($sb, 30);
$event->panel->add_block($sb);
}
if(is_a($event, 'ConfigSaveEvent')) {
$event->config->set_string_from_post("image_ilink");

View file

@ -1,11 +1,10 @@
<?php
class NavBlock {
var $header;
var $body;
class NavBlock extends Block {
public function NavBlock() {
$this->header = "Navigation";
$this->body = "<a href='".make_link("index")."'>Index</a>";
$this->section = "left";
$this->position = 0;
}
}
?>

View file

@ -1,5 +1,5 @@
<?php
class Page {
class GenericPage {
var $mode = "page";
var $type = "text/html";
@ -40,8 +40,7 @@ class Page {
var $subheading = "";
var $quicknav = "";
var $headers = array();
var $sideblocks = array();
var $mainblocks = array();
var $blocks = array();
public function set_title($title) {
$this->title = $title;
@ -60,14 +59,8 @@ class Page {
$this->headers[$position] = $line;
}
public function add_side_block($block, $position=50) {
while(isset($this->sideblocks[$position])) $position++;
$this->sideblocks[$position] = $block;
}
public function add_main_block($block, $position=50) {
while(isset($this->mainblocks[$position])) $position++;
$this->mainblocks[$position] = $block;
public function add_block($block) {
$this->blocks[] = $block;
}
// ==============================================
@ -80,10 +73,9 @@ class Page {
switch($this->mode) {
case "page":
header("Cache-control: no-cache");
ksort($this->sideblocks);
ksort($this->mainblocks);
$theme = $config->get_string("theme");
require_once "themes/$theme/default.php";
usort($this->blocks, "blockcmp");
$layout = new Layout();
$layout->display_page($this);
break;
case "data":
print $this->data;

View file

@ -6,6 +6,8 @@ class Paginator extends Block {
public function Paginator($page, $query, $page_number, $total_pages) {
$this->body = $this->build_paginator($page_number, $total_pages, $page, $query);
$this->section = "main";
$this->position = 90;
}
private function gen_page_link($base_url, $query, $page, $name) {

View file

@ -216,6 +216,57 @@ function CountExecs($db, $sql, $inputarray) {
$null = null; return $null;
}
function get_theme_object($file, $class) {
global $config;
$theme = $config->get_string("theme", "default");
if(file_exists("themes/$theme/$file.theme.php")) {
require_once "themes/$theme/$file.theme.php";
return new $class();
}
else {
require_once "ext/$file/theme.php";
return new $class();
}
}
function get_debug_info() {
global $config;
if($config->get_bool('debug_enabled')) {
if(function_exists('memory_get_usage')) {
$i_mem = sprintf("%5.2f", ((memory_get_usage()+512)/1024)/1024);
}
else {
$i_mem = "???";
}
if(function_exists('getrusage')) {
$ru = getrusage();
$i_utime = sprintf("%5.2f", ($ru["ru_utime.tv_sec"]*1e6+$ru["ru_utime.tv_usec"])/1000000);
$i_stime = sprintf("%5.2f", ($ru["ru_stime.tv_sec"]*1e6+$ru["ru_stime.tv_usec"])/1000000);
}
else {
$i_utime = "???";
$i_stime = "???";
}
$i_files = count(get_included_files());
global $_execs;
$debug = "<br>Took $i_utime + $i_stime seconds and {$i_mem}MB of RAM";
$debug .= "; Used $i_files files and $_execs queries";
}
else {
$debug = "";
}
return $debug;
}
function blockcmp($a, $b) {
if($a->position == $b->position) {
return 0;
}
else {
return ($a->position > $b->position);
}
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
* Things which should be in the core API *
@ -284,7 +335,7 @@ function _get_query_parts() {
return split('/', $path);
}
function get_page_request() {
function get_page_request($page_object) {
global $config;
$args = _get_query_parts();
@ -301,7 +352,7 @@ function get_page_request() {
$args = array_slice($args, 1);
}
return new PageRequestEvent($page, $args);
return new PageRequestEvent($page, $args, $page_object);
}
function get_user() {

View file

@ -11,8 +11,11 @@ class AddAliasEvent extends Event {
}
class AliasEditor extends Extension {
var $theme;
// event handler {{{
public function receive_event($event) {
if(is_null($this->theme)) $this->theme = get_theme_object("alias_editor", "AliasEditorTheme");
if(is_a($event, 'PageRequestEvent') && ($event->page == "alias")) {
global $user;
if($event->get_arg(0) == "add") {
@ -27,7 +30,7 @@ class AliasEditor extends Extension {
if(isset($_POST['oldtag'])) {
global $database;
$database->Execute("DELETE FROM aliases WHERE oldtag=?", array($_POST['oldtag']));
global $page;
$page->set_mode("redirect");
$page->set_redirect(make_link("admin"));
@ -36,10 +39,8 @@ class AliasEditor extends Extension {
}
else if($event->get_arg(0) == "list") {
global $page;
$page->set_title("Alias List");
$page->set_heading("Alias List");
$page->add_side_block(new NavBlock());
$page->add_main_block(new Block("Aliases", $this->build_aliases()));
global $database;
$this->theme->display_aliases($page, $database->db->GetAssoc("SELECT oldtag, newtag FROM aliases"), $user->is_admin());
}
else if($event->get_arg(0) == "export") {
global $page;
@ -65,66 +66,6 @@ class AliasEditor extends Extension {
}
}
// }}}
// admin page HTML {{{
private function build_aliases() {
global $database;
global $user;
if($user->is_admin()) {
$action = "<td>Action</td>";
$add = "
<tr>
<form action='".make_link("alias/add")."' method='POST'>
<td><input type='text' name='oldtag'></td>
<td><input type='text' name='newtag'></td>
<td><input type='submit' value='Add'></td>
</form>
</tr>
";
}
else {
$action = "";
$add = "";
}
$h_aliases = "";
$aliases = $database->db->GetAssoc("SELECT oldtag, newtag FROM aliases");
foreach($aliases as $old => $new) {
$h_old = html_escape($old);
$h_new = html_escape($new);
$h_aliases .= "<tr><td>$h_old</td><td>$h_new</td>";
if($user->is_admin()) {
$h_aliases .= "
<td>
<form action='".make_link("alias/remove")."' method='POST'>
<input type='hidden' name='oldtag' value='$h_old'>
<input type='submit' value='Remove'>
</form>
</td>
";
}
$h_aliases .= "</tr>";
}
$html = "
<table border='1'>
<thead><td>From</td><td>To</td>$action</thead>
$h_aliases
$add
</table>
<p><a href='".make_link("alias/export/aliases.csv")."'>Download as CSV</a></p>
";
return $html;
}
private function get_alias_csv() {
global $database;
$csv = "";
$aliases = $database->db->GetAssoc("SELECT oldtag, newtag FROM aliases");
foreach($aliases as $old => $new) {
$csv .= "$old,$new\n";
}
return $csv;
}
// }}}
}
add_event_listener(new AliasEditor());
?>

View file

@ -0,0 +1,54 @@
<?php
class AliasEditorTheme extends Themelet {
public function display_aliases($page, $aliases, $is_admin) {
if($is_admin) {
$action = "<td>Action</td>";
$add = "
<tr>
<form action='".make_link("alias/add")."' method='POST'>
<td><input type='text' name='oldtag'></td>
<td><input type='text' name='newtag'></td>
<td><input type='submit' value='Add'></td>
</form>
</tr>
";
}
else {
$action = "";
$add = "";
}
$h_aliases = "";
foreach($aliases as $old => $new) {
$h_old = html_escape($old);
$h_new = html_escape($new);
$h_aliases .= "<tr><td>$h_old</td><td>$h_new</td>";
if($is_admin) {
$h_aliases .= "
<td>
<form action='".make_link("alias/remove")."' method='POST'>
<input type='hidden' name='oldtag' value='$h_old'>
<input type='submit' value='Remove'>
</form>
</td>
";
}
$h_aliases .= "</tr>";
}
$html = "
<table border='1'>
<thead><td>From</td><td>To</td>$action</thead>
$h_aliases
$add
</table>
<p><a href='".make_link("alias/export/aliases.csv")."'>Download as CSV</a></p>
";
$page->set_title("Alias List");
$page->set_heading("Alias List");
$page->add_block(new NavBlock());
$page->add_block(new Block("Aliases", $html));
}
}
?>

View file

@ -1,24 +1,24 @@
<?php
class BulkAdd extends Extension {
var $theme;
// event handler {{{
public function receive_event($event) {
if(is_null($this->theme)) $this->theme = get_theme_object("bulk_add", "BulkAddTheme");
if(is_a($event, 'PageRequestEvent') && ($event->page == "bulk_add")) {
global $user;
if($user->is_admin() && isset($_POST['dir'])) {
set_time_limit(0);
global $page;
$page->set_title("Adding folder");
$page->set_heading("Adding folder");
$page->add_side_block(new NavBlock());
$this->theme->display_upload_results($event->page_object);
$this->add_dir($_POST['dir']);
}
}
if(is_a($event, 'AdminBuildingEvent')) {
global $page;
$page->add_main_block(new Block("Bulk Add", $this->build_bulkadd()));
$this->theme->display_admin_block($page);
}
}
// }}}
@ -29,12 +29,12 @@ class BulkAdd extends Extension {
$ok = false;
if(filesize($tmpname) > $config->get_int('upload_size')) {
// $page->add_main_block(new Block("Error with ".html_escape($filename),
// $page->add_block(new Block("Error with ".html_escape($filename),
// "File too large (".filesize($file['tmp_name'])." &gt; ".
// ($config->get_int('upload_size')).")"));
}
else if(!($info = getimagesize($tmpname))) {
// $page->add_main_block(new Block("Error with ".html_escape($file['name']),
// $page->add_block(new Block("Error with ".html_escape($file['name']),
// "PHP doesn't recognise this as an image file"));
}
else {
@ -53,7 +53,7 @@ class BulkAdd extends Extension {
global $page;
if(!is_dir($base)) {
$page->add_main_block(new Block("Error", "$base is not a directory"));
$this->theme->add_status("Error", "$base is not a directory");
}
$list = "";
@ -80,23 +80,7 @@ class BulkAdd extends Extension {
}
closedir($dir);
$page->add_main_block(new Block("Adding $subdir", $list));
}
// }}}
// admin page HTML {{{
private function build_bulkadd() {
$html = "
Add a folder full of images; any subfolders will have their names
used as tags for the images within.
<br>Note: this is the folder as seen by the server -- you need to
upload via FTP or something first.
<p><form action='".make_link("bulk_add")."' method='POST'>
Directory to add: <input type='text' name='dir' size='40'>
<input type='submit' value='Add'>
</form>
";
return $html;
$this->theme->add_status("Adding $subdir", $list);
}
// }}}
}

29
ext/bulk_add/theme.php Normal file
View file

@ -0,0 +1,29 @@
<?php
class BulkAddTheme extends Themelet {
public function display_upload_results($page) {
$page->set_title("Adding folder");
$page->set_heading("Adding folder");
$page->add_block(new NavBlock());
}
public function display_admin_block($page) {
$html = "
Add a folder full of images; any subfolders will have their names
used as tags for the images within.
<br>Note: this is the folder as seen by the server -- you need to
upload via FTP or something first.
<p><form action='".make_link("bulk_add")."' method='POST'>
Directory to add: <input type='text' name='dir' size='40'>
<input type='submit' value='Add'>
</form>
";
$page->add_block(new Block("Bulk Add", $html));
}
public function add_status($title, $body) {
$page->add_block(new Block($title, $body));
}
}
?>

View file

@ -49,8 +49,11 @@ class Comment { // {{{
} // }}}
class CommentList extends Extension {
var $theme;
// event handler {{{
public function receive_event($event) {
if(is_null($this->theme)) $this->theme = get_theme_object("comment", "CommentListTheme");
if(is_a($event, 'InitExtEvent')) {
global $config;
if($config->get_int("ext_comments_version") < 1) {
@ -64,13 +67,12 @@ class CommentList extends Extension {
}
else if($event->get_arg(0) == "delete") {
global $user;
global $page;
if($user->is_admin()) {
// FIXME: post, not args
if($event->count_args() == 3) {
send_event(new CommentDeletionEvent($event->get_arg(1)));
$page->set_mode("redirect");
$page->set_redirect(make_link("post/view/".$event->get_arg(2)));
$event->page_object->set_mode("redirect");
$event->page_object->set_redirect(make_link("post/view/".$event->get_arg(2)));
}
}
else {
@ -85,15 +87,21 @@ class CommentList extends Extension {
global $page;
global $config;
if($config->get_int("comment_count") > 0) {
$page->add_side_block(new Block("Comments", $this->build_recent_comments()), 50);
$page->add_block(new Block("Comments", $this->build_recent_comments(), "left"));
}
}
if(is_a($event, 'DisplayingImageEvent')) {
global $page;
$page->add_main_block(new Block("Comments",
if($this->can_comment()) {
$page->add_block(new Block("Comments",
$this->build_image_comments($event->image->id).
$this->build_postbox($event->image->id)), 50);
$this->theme->build_postbox($event->image->id), "main", 30));
}
else {
$page->add_block(new Block("Comments",
$this->build_image_comments($event->image->id), "main", 30));
}
}
if(is_a($event, 'ImageDeletionEvent')) {
@ -115,7 +123,7 @@ class CommentList extends Extension {
$sb->add_int_option("comment_count");
$sb->add_label(" recent comments on the index");
$sb->add_text_option("comment_wordpress_key", "<br>Akismet Key ");
$event->panel->add_main_block($sb);
$event->panel->add_block($sb);
}
if(is_a($event, 'ConfigSaveEvent')) {
$event->config->set_bool_from_post("comment_anon");
@ -164,42 +172,19 @@ class CommentList extends Extension {
";
$result = $database->Execute($get_threads, array($start, $threads_per_page));
$total_pages = (int)($database->db->GetOne("SELECT COUNT(distinct image_id) AS count FROM comments") / 10);
$page->set_title("Comments");
$page->set_heading("Comments");
$page->add_side_block(new Block("Navigation", $this->build_navigation($current_page, $total_pages)));
$page->add_main_block(new Paginator("comment/list", null, $current_page, $total_pages), 90);
$this->theme->display_page_start($page, $current_page, $total_pages);
$n = 10;
while(!$result->EOF) {
$image = $database->get_image($result->fields["image_id"]);
$html = "<div style='text-align: left'>";
$html .= "<div style='float: left; margin-right: 16px;'>" . build_thumb_html($image) . "</div>";
$html .= $this->build_image_comments($image->id);
$html .= "</div>";
$html .= "<div style='clear:both;'>".($this->build_postbox($image->id))."</div>";
$page->add_main_block(new Block("{$image->id}: ".($image->get_tag_list()), $html), $n);
$comments = $this->build_image_comments($image->id);
$this->theme->add_comment_list($page, $image, $comments, $n, $this->can_comment());
$n += 1;
$result->MoveNext();
}
}
private function build_navigation($page_number, $total_pages) {
$prev = $page_number - 1;
$next = $page_number + 1;
$h_prev = ($page_number <= 1) ? "Prev" :
"<a href='".make_link("comment/list/$prev")."'>Prev</a>";
$h_index = "<a href='".make_link("index")."'>Index</a>";
$h_next = ($page_number >= $total_pages) ? "Next" :
"<a href='".make_link("comment/list/$next")."'>Next</a>";
return "$h_prev | $h_index | $h_next";
}
private function build_image_comments($image_id) {
@ -236,22 +221,6 @@ class CommentList extends Extension {
return $html;
}
private function build_postbox($image_id) {
if($this->can_comment()) {
$i_image_id = int_escape($image_id);
return "
<form action='".make_link("comment/add")."' method='POST'>
<input type='hidden' name='image_id' value='$i_image_id' />
<textarea name='comment' rows='5' cols='50'></textarea>
<br><input type='submit' value='Post' />
</form>
";
}
else {
return "<p><small>You need to create an account before you can comment</small></p>";
}
}
private function query_to_html($query, $args, $trim=false) {
global $database;
global $config;
@ -327,7 +296,7 @@ class CommentList extends Extension {
$page->set_title("Error");
$page->set_heading("Error");
$page->add_side_block(new NavBlock());
$page->add_block(new NavBlock());
if(!$config->get_bool('comment_anon') && $user->is_anonymous()) {
$page->add_main_block(new Block("Permission Denied", "Anonymous posting has been disabled"));
}

52
ext/comment/theme.php Normal file
View file

@ -0,0 +1,52 @@
<?php
class CommentListTheme extends Themelet {
public function display_page_start($page, $current_page, $total_pages) {
$page->set_title("Comments");
$page->set_heading("Comments");
$page->add_block(new Block("Navigation", $this->build_navigation($current_page, $total_pages), "left"));
$page->add_block(new Paginator("comment/list", null, $current_page, $total_pages), 90);
}
private function build_navigation($page_number, $total_pages) {
$prev = $page_number - 1;
$next = $page_number + 1;
$h_prev = ($page_number <= 1) ? "Prev" :
"<a href='".make_link("comment/list/$prev")."'>Prev</a>";
$h_index = "<a href='".make_link("index")."'>Index</a>";
$h_next = ($page_number >= $total_pages) ? "Next" :
"<a href='".make_link("comment/list/$next")."'>Next</a>";
return "$h_prev | $h_index | $h_next";
}
// FIXME: privatise this
public function build_postbox($image_id) {
$i_image_id = int_escape($image_id);
return "
<form action='".make_link("comment/add")."' method='POST'>
<input type='hidden' name='image_id' value='$i_image_id' />
<textarea name='comment' rows='5' cols='50'></textarea>
<br><input type='submit' value='Post' />
</form>
";
}
public function add_comment_list($page, $image, $comments, $position, $with_postbox) {
$html = "<div style='text-align: left'>";
$html .= "<div style='float: left; margin-right: 16px;'>" . build_thumb_html($image) . "</div>";
$html .= $comments;
$html .= "</div>";
if($with_postbox) {
$html .= "<div style='clear:both;'>".($this->build_postbox($image->id))."</div>";
}
else {
$html .= "<div style='clear:both;'><p><small>You need to create an account before you can comment</small></p></div>";
}
$page->add_block(new Block("{$image->id}: ".($image->get_tag_list()), $html, "main", $position));
}
}
?>

View file

@ -1,15 +1,18 @@
<?php
class Downtime extends Extension {
// event handler {{{
var $theme;
public function receive_event($event) {
if(is_null($this->theme)) $this->theme = get_theme_object("downtime", "DowntimeTheme");
$this->check_downtime($event);
if(is_a($event, 'SetupBuildingEvent')) {
$sb = new SetupBlock("Downtime");
$sb->add_bool_option("downtime", "Disable non-admin access: ");
$sb->add_longtext_option("downtime_message", "<br>");
$event->panel->add_main_block($sb);
$event->panel->add_block($sb);
}
if(is_a($event, 'ConfigSaveEvent')) {
$event->config->set_bool_from_post("downtime");
@ -18,14 +21,11 @@ class Downtime extends Extension {
if(is_a($event, 'PageRequestEvent')) {
global $config;
if($config->get_bool("downtime")) {
global $page;
$page->add_side_block(new Block("Downtime", "<span style='font-size: 1.5em'><b>DOWNTIME MODE IS ON!</b></span>"), 0);
$this->theme->display_notification($event->page_object);
}
}
}
// }}}
// do things {{{
private function check_downtime($event) {
global $user;
global $config;
@ -33,18 +33,7 @@ class Downtime extends Extension {
if($config->get_bool("downtime") && !$user->is_admin() &&
is_a($event, 'PageRequestEvent') && !$this->is_safe_page($event)) {
$msg = $config->get_string("downtime_message");
header("HTTP/1.0 503 Service Temporarily Unavailable");
print <<<EOD
<html>
<head>
<title>Downtime</title>
</head>
<body>
$msg
</body>
</html>
EOD;
exit;
$this->theme->display_message($msg);
}
}
@ -52,7 +41,6 @@ EOD;
if($event->page == "user" && $event->get_arg(0) == "login") return true;
else return false;
}
// }}}
}
add_event_listener(new Downtime(), 10);
?>

24
ext/downtime/theme.php Normal file
View file

@ -0,0 +1,24 @@
<?php
class DowntimeTheme Extends Themelet {
public function display_notification($page) {
$page->add_block(new Block("Downtime",
"<span style='font-size: 1.5em'><b>DOWNTIME MODE IS ON!</b></span>", "left", 0));
}
public function display_message($message) {
header("HTTP/1.0 503 Service Temporarily Unavailable");
print <<<EOD
<html>
<head>
<title>Downtime</title>
</head>
<body>
$message
</body>
</html>
EOD;
exit;
}
}
?>

View file

@ -1,101 +1,64 @@
<?php
class ET extends Extension {
var $theme;
// event handler {{{
public function receive_event($event) {
if(is_a($event, 'PageRequestEvent') && ($event->page == "phone_home")) {
if(is_null($this->theme)) $this->theme = get_theme_object("et", "ETTheme");
if(is_a($event, 'PageRequestEvent') && ($event->page == "system_info")) {
global $user;
if($user->is_admin()) {
$this->phone_home();
$this->theme->display_info_page($event->page_object, $this->get_info());
}
}
if(is_a($event, 'AdminBuildingEvent')) {
global $page;
$page->add_main_block(new Block("Gather System Info", $this->build_phone_home()), 99);
if(is_a($event, 'UserBlockBuildingEvent')) {
if($event->user->is_admin()) {
$event->add_link("System Info", make_link("system_info"));
}
}
}
// }}}
// do it {{{
private function phone_home() {
global $page;
$page->set_title("System Info");
$page->set_heading("System Info");
$page->add_side_block(new NavBlock());
$page->add_main_block(new Block("Data which is to be sent:", $this->build_data_form()));
}
private function build_data_form() {
private function get_info() {
global $database;
global $config;
global $_event_listeners; // yay for using secret globals \o/
$data = "";
$info = array();
$info['site_title'] = $config->get_string("title");
$info['site_theme'] = $config->get_string("theme");
$info['site_genre'] = "[please write something here]";
$info['site_url'] = isset($_SERVER['SCRIPT_URI']) ? dirname($_SERVER['SCRIPT_URI']) : "???";
$data .= "Optional:\n";
$data .= "Add this site to the public shimmie users list: No\n";
$data .= "Site title: ".($config->get_string("title"))."\n";
$data .= "Theme: ".($config->get_string("theme"))."\n";
$data .= "Genre: [please write something here]\n";
$data .= "\nSystem stats:\n";
$data .= "PHP: ".phpversion()."\n";
$data .= "OS: ".php_uname()."\n";
$data .= "Server: ".($_SERVER["SERVER_SOFTWARE"])."\n";
include "config.php";
$info['sys_shimmie'] = $config->get_string("version");
$info['sys_php'] = phpversion();
$info['sys_os'] = php_uname();
$info['sys_server'] = $_SERVER["SERVER_SOFTWARE"];
include "config.php"; // more magical hax
$proto = preg_replace("#(.*)://.*#", "$1", $database_dsn);
$db = $database->db->ServerInfo();
$data .= "Database: $proto / {$db['version']}\n";
$info['sys_db'] = "$proto / {$db['version']}";
$data .= "\nShimmie stats:\n";
$uri = isset($_SERVER['SCRIPT_URI']) ? dirname($_SERVER['SCRIPT_URI']) : "???";
$data .= "URL: ".($uri)."\n";
$data .= "Version: ".($config->get_string("version"))."\n";
$data .= "Images: ".($database->db->GetOne("SELECT COUNT(*) FROM images"))."\n";
$data .= "Comments: ".($database->db->GetOne("SELECT COUNT(*) FROM comments"))."\n";
$data .= "Users: ".($database->db->GetOne("SELECT COUNT(*) FROM users"))."\n";
$data .= "Tags: ".($database->db->GetOne("SELECT COUNT(*) FROM tags"))."\n";
$info['stat_images'] = $database->db->GetOne("SELECT COUNT(*) FROM images");
$info['stat_comments'] = $database->db->GetOne("SELECT COUNT(*) FROM comments");
$info['stat_users'] = $database->db->GetOne("SELECT COUNT(*) FROM users");
$info['stat_tags'] = $database->db->GetOne("SELECT COUNT(*) FROM tags");
$els = array();
foreach($_event_listeners as $el) {
$els[] = get_class($el);
}
$data .= "Extensions: ".join(", ", $els)."\n";
$info['sys_extensions'] = join(', ', $els);
//$cfs = array();
//foreach($database->db->GetAll("SELECT name, value FROM config") as $pair) {
// $cfs[] = $pair['name']."=".$pair['value'];
//}
//$data .= "Config: ".join(", ", $cfs);
//$info[''] = "Config: ".join(", ", $cfs);
$html = "
<form action='http://shimmie.shishnet.org/register.php' method='POST'>
<input type='hidden' name='registration_api' value='1'>
<textarea name='data' rows='20' cols='80'>$data</textarea>
<br><input type='submit' value='Click to send to Shish'>
<br>Your stats are useful so that I know which combinations
of web servers / databases / etc I need to support,
<br>and so
that I can get some idea of how people use shimmie generally
</form>
";
return $html;
}
// }}}
// admin page HTML {{{
private function build_phone_home() {
global $database;
$h_bans = "";
$html = "
This button will gather various bits of information about
your system (PHP version, database, etc) which will be
useful in debugging~
<p><form action='".make_link("phone_home")."' method='POST'>
<input type='submit' value='Gather Info'>
</form>
";
return $html;
return $info;
}
// }}}
}

47
ext/et/theme.php Normal file
View file

@ -0,0 +1,47 @@
<?php
class ETTheme extends Themelet {
public function display_info_page($page, $info) {
$page->set_title("System Info");
$page->set_heading("System Info");
$page->add_block(new NavBlock());
$page->add_block(new Block("Data which is to be sent:", $this->build_data_form($info)));
}
private function build_data_form($info) {
$data = <<<EOD
Optional:
Add this site to the public shimmie users list: No
Site title: {$info['site_title']}
Theme: {$info['site_theme']}
Genre: {$info['site_genre']}
URL: {$info['site_url']}
System stats:
Shimmie: {$info['sys_shimmie']}
PHP: {$info['sys_php']}
OS: {$info['sys_os']}
Server: {$info['sys_server']}
Database: {$info['sys_db']}
Extensions: {$info['sys_extensions']}
Shimmie stats:
Images: {$info['stat_images']}
Comments: {$info['stat_comments']}
Users: {$info['stat_users']}
Tags: {$info['stat_tags']}
EOD;
$html = <<<EOD
<form action='http://shimmie.shishnet.org/register.php' method='POST'>
<input type='hidden' name='registration_api' value='1'>
<textarea name='data' rows='20' cols='80'>$data</textarea>
<br><input type='submit' value='Click to send to Shish'>
<br>Your stats are useful so that I know which combinations
of web servers / databases / etc I need to support,
<br>and so that I can get some idea of how people use shimmie generally
</form>
EOD;
return $html;
}
}
?>

View file

@ -5,13 +5,13 @@ class Handle404 extends Extension {
if(is_a($event, 'PageRequestEvent')) {
global $page;
// hax.
if($page->mode == "page" && (!isset($page->mainblocks) || count($page->mainblocks) == 0)) {
if($page->mode == "page" && (!isset($page->blocks) || count($page->blocks) == 0)) {
$h_pagename = html_escape($event->page);
header("HTTP/1.0 404 Page Not Found");
$page->set_title("404");
$page->set_heading("404 - No Handler Found");
$page->add_side_block(new NavBlock());
$page->add_main_block(new Block("Explanation", "No handler could be found for the page '$h_pagename'"));
$page->add_block(new NavBlock());
$page->add_block(new Block("Explanation", "No handler could be found for the page '$h_pagename'"));
}
}
}

7
ext/handle_404/theme.php Normal file
View file

@ -0,0 +1,7 @@
<?php
/*
* The 404-handler is very tightly tied to the default theme,
* such that it would be easier to write a new handler for a
* new theme than to alter this one...
*/
?>

View file

@ -24,8 +24,11 @@ class AddIPBanEvent extends Event {
// }}}
class IPBan extends Extension {
var $theme;
// event handler {{{
public function receive_event($event) {
if(is_null($this->theme)) $this->theme = get_theme_object("ipban", "IPBanTheme");
if(is_a($event, 'InitExtEvent')) {
global $config;
if($config->get_int("ext_ipban_version") < 1) {
@ -69,7 +72,7 @@ class IPBan extends Extension {
if(is_a($event, 'AdminBuildingEvent')) {
global $page;
$page->add_main_block(new Block("Edit IP Bans", $this->build_ip_bans()));
$this->theme->display_bans($page, $this->get_bans());
}
}
// }}}
@ -131,43 +134,6 @@ class IPBan extends Extension {
$database->Execute("DELETE FROM bans WHERE ip = ?", array($ip));
}
// }}}
// admin page HTML {{{
private function build_ip_bans() {
global $database;
$h_bans = "";
$bans = $this->get_bans();
foreach($bans as $ban) {
$h_bans .= "
<tr>
<td>{$ban['ip']}</td>
<td>{$ban['reason']}</td>
<td>{$ban['end']}</td>
<td>
<form action='".make_link("ip_ban/remove")."' method='POST'>
<input type='hidden' name='ip' value='{$ban['ip']}'>
<input type='submit' value='Remove'>
</form>
</td>
</tr>
";
}
$html = "
<table border='1'>
<thead><td>IP</td><td>Reason</td><td>Until</td><td>Action</td></thead>
$h_bans
<tr>
<form action='".make_link("ip_ban/add")."' method='POST'>
<td><input type='text' name='ip'></td>
<td><input type='text' name='reason'></td>
<td><input type='text' name='end'></td>
<td><input type='submit' value='Ban'></td>
</form>
</tr>
</table>
";
return $html;
}
// }}}
}
add_event_listener(new IPBan(), 10);
?>

38
ext/ipban/theme.php Normal file
View file

@ -0,0 +1,38 @@
<?php
class IPBanTheme extends Themelet {
public function display_bans($page, $bans) {
$h_bans = "";
foreach($bans as $ban) {
$h_bans .= "
<tr>
<td>{$ban['ip']}</td>
<td>{$ban['reason']}</td>
<td>{$ban['end']}</td>
<td>
<form action='".make_link("ip_ban/remove")."' method='POST'>
<input type='hidden' name='ip' value='{$ban['ip']}'>
<input type='submit' value='Remove'>
</form>
</td>
</tr>
";
}
$html = "
<table border='1'>
<thead><td>IP</td><td>Reason</td><td>Until</td><td>Action</td></thead>
$h_bans
<tr>
<form action='".make_link("ip_ban/add")."' method='POST'>
<td><input type='text' name='ip'></td>
<td><input type='text' name='reason'></td>
<td><input type='text' name='end'></td>
<td><input type='submit' value='Ban'></td>
</form>
</tr>
</table>
";
$page->add_block(new Block("Edit IP Bans", $html));
}
}
?>

View file

@ -1,18 +1,21 @@
<?php
class News extends Extension {
var $theme;
public function receive_event($event) {
global $page;
if(is_null($this->theme)) $this->theme = get_theme_object("news", "NewsTheme");
if(is_a($event, 'PageRequestEvent') && ($event->page == "index")) {
global $config;
if(strlen($config->get_string("news_text")) > 0) {
$page->add_side_block(new Block("Note", $config->get_string("news_text")), 5);
$this->theme->display_news($event->page_object, $config->get_string("news_text"));
}
}
if(is_a($event, 'SetupBuildingEvent')) {
$sb = new SetupBlock("News");
$sb->add_longtext_option("news_text");
$event->panel->add_main_block($sb);
$event->panel->add_block($sb);
}
if(is_a($event, 'ConfigSaveEvent')) {
$event->config->set_string_from_post("news_text");

8
ext/news/theme.php Normal file
View file

@ -0,0 +1,8 @@
<?php
class NewsTheme extends Themelet {
public function display_news($page, $text) {
$page->add_block(new Block("Note", $text, "left", 5));
}
}
?>

View file

@ -1,8 +1,11 @@
<?php
class RegenThumb extends Extension {
var $theme;
// event handler {{{
public function receive_event($event) {
if(is_null($this->theme)) $this->theme = get_theme_object("regen_thumb", "RegenThumbTheme");
if(is_a($event, 'PageRequestEvent') && ($event->page == "regen_thumb")) {
global $user;
if($user->is_admin() && isset($_POST['program']) && isset($_POST['image_id'])) {
@ -14,7 +17,7 @@ class RegenThumb extends Extension {
global $page;
global $user;
if($user->is_admin()) {
$page->add_side_block(new Block("Regen Thumb", $this->build_regen_buttons($event->image)));
$this->theme->display_buttons($page, $event->image->id);
}
}
}
@ -48,11 +51,7 @@ class RegenThumb extends Extension {
}
global $page;
$page->set_title("Thumbnail Regenerated");
$page->set_heading("Thumbnail Regenerated");
$page->add_header("<meta http-equiv=\"cache-control\" content=\"no-cache\">");
$page->add_side_block(new NavBlock());
$page->add_main_block(new Block("Thumbnail", build_thumb_html($image)));
$this->theme->display_results($page, $image);
}
private function check_filename($filename) {
@ -110,24 +109,6 @@ class RegenThumb extends Extension {
}
}
// }}}
// page building {{{
private function build_regen_buttons($image) {
global $user;
if($user->is_admin()) {
return "
<form action='".make_link("regen_thumb")."' method='POST'>
<input type='hidden' name='image_id' value='{$image->id}'>
<select name='program'>
<option value='convert'>ImageMagick</option>
<option value='gd'>GD</option>
<!-- <option value='epeg'>EPEG (for JPEG only)</option> -->
</select>
<input type='submit' value='Regenerate'>
</form>
";
}
}
// }}}
}
add_event_listener(new RegenThumb());
?>

27
ext/regen_thumb/theme.php Normal file
View file

@ -0,0 +1,27 @@
<?php
class RegenThumbTheme extends Themelet {
public function display_buttons($page, $image_id) {
$html = "
<form action='".make_link("regen_thumb")."' method='POST'>
<input type='hidden' name='image_id' value='$image_id'>
<select name='program'>
<option value='convert'>ImageMagick</option>
<option value='gd'>GD</option>
<!-- <option value='epeg'>EPEG (for JPEG only)</option> -->
</select>
<input type='submit' value='Regenerate'>
</form>
";
$page->add_block(new Block("Regen Thumb", $html, "left"));
}
public function display_results($page, $image) {
$page->set_title("Thumbnail Regenerated");
$page->set_heading("Thumbnail Regenerated");
$page->add_header("<meta http-equiv=\"cache-control\" content=\"no-cache\">");
$page->add_block(new NavBlock());
$page->add_block(new Block("Thumbnail", build_thumb_html($image)));
}
}
?>

5
ext/rss_images/theme.php Normal file
View file

@ -0,0 +1,5 @@
<?php
/*
* The RSS plugin does no HTML output
*/
?>

View file

@ -1,35 +1,39 @@
<?php
class TagList extends Extension {
var $theme = null;
// event handling {{{
public function receive_event($event) {
if($this->theme == null) $this->theme = get_theme_object("tag_list", "TagListTheme");
if(is_a($event, 'PageRequestEvent') && ($event->page == "tags")) {
global $page;
$page->set_title("Tag List");
$page->add_side_block(new Block("Navigation", $this->build_navigation()), 0);
$this->theme->set_navigation($this->build_navigation());
switch($event->get_arg(0)) {
default:
case 'map':
$page->set_heading("Tag Map");
$page->add_main_block(new Block("Tags", $this->build_tag_map()));
$this->theme->set_heading("Tag Map");
$this->theme->set_tag_list($this->build_tag_map());
break;
case 'alphabetic':
$page->set_heading("Alphabetic Tag List");
$page->add_main_block(new Block("Tags", $this->build_tag_alphabetic()));
$this->theme->set_heading("Alphabetic Tag List");
$this->theme->set_tag_list($this->build_tag_alphabetic());
break;
case 'popularity':
$page->set_heading("Tag List by Popularity");
$page->add_main_block(new Block("Tags", $this->build_tag_popularity()));
$this->theme->set_heading("Tag List by Popularity");
$this->theme->set_tag_list($this->build_tag_popularity());
break;
}
$this->theme->display_page($page);
}
if(is_a($event, 'PageRequestEvent') && ($event->page == "index")) {
global $config;
global $page;
if($config->get_int('tag_list_length') > 0) {
if(isset($_GET['search'])) {
$this->add_refine_block($page, $_GET['search']);
$this->add_refine_block($page, tag_explode($_GET['search']));
}
else {
$this->add_popular_block($page);
@ -41,20 +45,20 @@ class TagList extends Extension {
global $page;
global $config;
if($config->get_int('tag_list_length') > 0) {
$page->add_side_block(new Block("Related Tags", $this->get_related_tags($event->get_image())), 60);
$this->add_related_block($page, $event->image);
}
}
if(is_a($event, 'SetupBuildingEvent')) {
$sb = new SetupBlock("Tag Map Options");
$sb->add_int_option("tags_min", "Ignore tags used fewer than "); $sb->add_label(" times");
$event->panel->add_main_block($sb);
$event->panel->add_block($sb);
$sb = new SetupBlock("Popular / Related Tag List");
$sb->add_int_option("tag_list_length", "Show top "); $sb->add_label(" tags");
$sb->add_text_option("info_link", "<br>Tag info link: ");
$sb->add_bool_option("tag_list_numbers", "<br>Show tag counts: ");
$event->panel->add_main_block($sb);
$event->panel->add_block($sb);
}
if(is_a($event, 'ConfigSaveEvent')) {
$event->config->set_int_from_post("tags_min");
@ -158,40 +162,8 @@ class TagList extends Extension {
return $html;
}
// }}}
// common {{{
private function build_tag_list_html($query, $args, $callback=null, $cbdata=null) {
global $database;
global $config;
$n = 0;
$html = "";
$result = $database->Execute($query, $args);
if($result->RecordCount() == 0) return false;
while(!$result->EOF) {
$row = $result->fields;
$tag = $row['tag'];
$h_tag = html_escape($tag);
$h_tag_no_underscores = str_replace("_", " ", $h_tag);
$count = $row['count'];
if($n++) $html .= "<br/>";
$link = $this->tag_link($row['tag']);
$html .= "<a class='tag_name' href='$link'>$h_tag_no_underscores</a>\n";
if(!is_null($callback)) {
$html .= $this->$callback($tag, $count, $cbdata);
}
if(!is_null($config->get_string('info_link'))) {
$link = str_replace('$tag', $tag, $config->get_string('info_link'));
$html .= " <a class='tag_info_link' href='$link'>?</a>\n";
}
$result->MoveNext();
}
$result->Close();
return $html;
}
// }}}
// get related {{{
private function get_related_tags($image) {
// blocks {{{
private function add_related_block($page, $image) {
global $database;
global $config;
@ -213,10 +185,12 @@ class TagList extends Extension {
";
$args = array($image->id, $config->get_int('tag_list_length'));
return $this->build_tag_list_html($query, $args);
$tags = $database->db->GetAll($query, $args);
if(count($tags) > 0) {
$this->theme->display_related_block($page, $tags);
}
}
// }}}
// get popular {{{
private function add_popular_block($page) {
global $database;
global $config;
@ -230,23 +204,12 @@ class TagList extends Extension {
";
$args = array($config->get_int('tag_list_length'));
if($config->get_bool('tag_list_numbers')) {
$html = $this->build_tag_list_html($query, $args, "add_count");
}
else {
$html = $this->build_tag_list_html($query, $args);
}
if($html) {
$html .= "<p><a class='more' href='".make_link("tags")."'>Full List</a>\n";
$page->add_side_block(new Block("Popular Tags", $html), 60);
$tags = $database->db->GetAll($query, $args);
if(count($tags) > 0) {
$this->theme->display_popular_block($page, $tags);
}
}
private function add_count($tag, $count, $data) {
return " <span class='tag_count'>($count)</span>";
}
// }}}
// get refine {{{
private function add_refine_block($page, $search) {
global $database;
global $config;
@ -269,53 +232,9 @@ class TagList extends Extension {
";
$args = array($config->get_int('tag_list_length'));
$tag_list = $this->build_tag_list_html($query, $args, "ars", $tags);
if($tag_list) {
$page->add_side_block(new Block("Refine Search", $tag_list), 60);
}
}
private function ars($tag, $count, $tags) {
$html = "";
$html .= " <span class='ars'>(";
$html .= $this->get_add_link($tags, $tag);
$html .= $this->get_remove_link($tags, $tag);
$html .= $this->get_subtract_link($tags, $tag);
$html .= ")</span>";
return $html;
}
private function get_remove_link($tags, $tag) {
if(!in_array($tag, $tags) && !in_array("-$tag", $tags)) {
return "";
}
else {
$tags = array_remove($tags, $tag);
$tags = array_remove($tags, "-$tag");
return "<a href='".make_link("index", "search=".url_escape(join(' ', $tags)))."' title='Remove' rel='nofollow'>R</a>";
}
}
private function get_add_link($tags, $tag) {
if(in_array($tag, $tags)) {
return "";
}
else {
$tags = array_remove($tags, "-$tag");
$tags = array_add($tags, $tag);
return "<a href='".make_link("index", "search=".url_escape(join(' ', $tags)))."' title='Add' rel='nofollow'>A</a>";
}
}
private function get_subtract_link($tags, $tag) {
if(in_array("-$tag", $tags)) {
return "";
}
else {
$tags = array_remove($tags, $tag);
$tags = array_add($tags, "-$tag");
return "<a href='".make_link("index", "search=".url_escape(join(' ', $tags)))."' title='Subtract' rel='nofollow'>S</a>";
$tags = $database->db->GetAll($query, $args);
if(count($tags) > 0) {
$this->theme->display_refine_block($page, $tags, $search);
}
}
// }}}

159
ext/tag_list/theme.php Normal file
View file

@ -0,0 +1,159 @@
<?php
class TagListTheme extends Themelet {
var $heading = "";
var $list = "";
public function set_heading($text) {
$this->heading = $text;
}
public function set_tag_list($list) {
$this->list = $list;
}
public function set_navigation($nav) {
$this->navigation = $nav;
}
public function display_page($page) {
$page->set_title("Tag List");
$page->set_heading($this->heading);
$page->add_block(new Block("Tags", $this->list));
$page->add_block(new Block("Navigation", $this->navigation, "left", 0));
}
// =======================================================================
public function display_related_block($page, $tag_infos) {
global $config;
$html = "";
$n = 0;
foreach($tag_infos as $row) {
$tag = $row['tag'];
$h_tag = html_escape($tag);
$h_tag_no_underscores = str_replace("_", " ", $h_tag);
$count = $row['count'];
if($n++) $html .= "<br/>";
$link = $this->tag_link($row['tag']);
$html .= "<a class='tag_name' href='$link'>$h_tag_no_underscores</a>\n";
if(!is_null($config->get_string('info_link'))) {
$link = str_replace('$tag', $tag, $config->get_string('info_link'));
$html .= " <a class='tag_info_link' href='$link'>?</a>\n";
}
}
$page->add_block(new Block("Related", $html, "left"));
}
/*
* $tag_infos = array(
* array('tag' => $tag, 'count' => $number_of_uses),
* ...
* )
*/
public function display_popular_block($page, $tag_infos) {
global $config;
$html = "";
$n = 0;
foreach($tag_infos as $row) {
$tag = $row['tag'];
$h_tag = html_escape($tag);
$h_tag_no_underscores = str_replace("_", " ", $h_tag);
$count = $row['count'];
if($n++) $html .= "<br/>";
$link = $this->tag_link($row['tag']);
$html .= "<a class='tag_name' href='$link'>$h_tag_no_underscores</a>\n";
if($config->get_bool("tag_list_numbers")) {
$html .= " <span class='tag_count'>($count)</span>";
}
if(!is_null($config->get_string('info_link'))) {
$link = str_replace('$tag', $tag, $config->get_string('info_link'));
$html .= " <a class='tag_info_link' href='$link'>?</a>\n";
}
}
$html .= "<p><a class='more' href='".make_link("tags")."'>Full List</a>\n";
$page->add_block(new Block("Popular Tags", $html, "left", 60));
}
/*
* $tag_infos = array(
* array('tag' => $tag),
* ...
* )
* $search = the current array of tags being searched for
*/
public function display_refine_block($page, $tag_infos, $search) {
global $config;
$html = "";
$n = 0;
foreach($tag_infos as $row) {
$tag = $row['tag'];
$h_tag = html_escape($tag);
$h_tag_no_underscores = str_replace("_", " ", $h_tag);
if($n++) $html .= "<br/>";
$link = $this->tag_link($row['tag']);
$html .= "<a class='tag_name' href='$link'>$h_tag_no_underscores</a>\n";
$html .= $this->ars($tag, $search);
if(!is_null($config->get_string('info_link'))) {
$link = str_replace('$tag', $tag, $config->get_string('info_link'));
$html .= " <a class='tag_info_link' href='$link'>?</a>\n";
}
}
$page->add_block(new Block("Refine Search", $html, "left", 60));
}
private function ars($tag, $tags) {
$html = "";
$html .= " <span class='ars'>(";
$html .= $this->get_add_link($tags, $tag);
$html .= $this->get_remove_link($tags, $tag);
$html .= $this->get_subtract_link($tags, $tag);
$html .= ")</span>";
return $html;
}
private function get_remove_link($tags, $tag) {
if(!in_array($tag, $tags) && !in_array("-$tag", $tags)) {
return "";
}
else {
$tags = array_remove($tags, $tag);
$tags = array_remove($tags, "-$tag");
return "<a href='".$this->tag_link(join(' ', $tags))."' title='Remove' rel='nofollow'>R</a>";
}
}
private function get_add_link($tags, $tag) {
if(in_array($tag, $tags)) {
return "";
}
else {
$tags = array_remove($tags, "-$tag");
$tags = array_add($tags, $tag);
return "<a href='".$this->tag_link(join(' ', $tags))."' title='Add' rel='nofollow'>A</a>";
}
}
private function get_subtract_link($tags, $tag) {
if(in_array("-$tag", $tags)) {
return "";
}
else {
$tags = array_remove($tags, $tag);
$tags = array_add($tags, "-$tag");
return "<a href='".$this->tag_link(join(' ', $tags))."' title='Subtract' rel='nofollow'>S</a>";
}
}
private function tag_link($tag) {
return make_link("index", "search=".url_escape($tag));
}
}
?>

View file

@ -4,12 +4,14 @@ define("UPLOAD_DEFAULT_MAX_SIZE", 256000);
define("UPLOAD_DEFAULT_COUNT", 3);
class Upload extends Extension {
var $theme;
// event handling {{{
public function receive_event($event) {
global $page;
if(is_null($this->theme)) $this->theme = get_theme_object("upload", "UploadTheme");
if(is_a($event, 'PageRequestEvent') && ($event->page == "index")) {
if($this->can_upload()) {
$page->add_side_block(new Block("Upload", $this->build_upload_block()), 20);
$this->theme->display_block($event->page_object);
}
}
if(is_a($event, 'PageRequestEvent') && ($event->page == "upload")) {
@ -21,22 +23,20 @@ class Upload extends Extension {
$ok = $ok & $this->try_upload($file);
}
$this->show_result($ok);
$this->theme->display_upload_status($event->page_object, $ok);
}
else {
$page->set_title("Upload Denied");
$page->set_heading("Upload Denied");
$page->add_side_block(new NavBlock());
$page->add_main_block(new Block("Error", "Anonymous posting is disabled"));
$this->theme->display_error($event->page_object, "Upload Denied", "Anonymous posting is disabled");
}
}
if(is_a($event, 'SetupBuildingEvent')) {
$sb = new SetupBlock("Upload");
$sb->position = 10;
$sb->add_int_option("upload_count", "Max uploads: ");
$sb->add_shorthand_int_option("upload_size", "<br>Max size per file: ");
$sb->add_bool_option("upload_anon", "<br>Allow anonymous upoads: ");
$event->panel->add_main_block($sb, 10);
$sb->add_bool_option("upload_anon", "<br>Allow anonymous uploads: ");
$event->panel->add_block($sb);
}
if(is_a($event, 'ConfigSaveEvent')) {
$event->config->set_int_from_post("upload_count");
@ -62,13 +62,13 @@ class Upload extends Extension {
$ok = true;
}
else if(filesize($file['tmp_name']) > $config->get_int('upload_size', UPLOAD_DEFAULT_MAX_SIZE)) {
$page->add_main_block(new Block("Error with ".html_escape($file['name']),
$this->theme->display_upload_error($page, "Error with ".html_escape($file['name']),
"File too large (".filesize($file['tmp_name'])." &gt; ".
($config->get_int('upload_size', UPLOAD_DEFAULT_MAX_SIZE)).")"));
($config->get_int('upload_size', UPLOAD_DEFAULT_MAX_SIZE)).")");
}
else if(!($info = getimagesize($file['tmp_name']))) {
$page->add_main_block(new Block("Error with ".html_escape($file['name']),
"PHP doesn't recognise this as an image file"));
$this->theme->display_upload_error("Error with ".html_escape($file['name']),
"PHP doesn't recognise this as an image file");
}
else {
$image = new Image($file['tmp_name'], $file['name'], $_POST['tags']);
@ -78,53 +78,13 @@ class Upload extends Extension {
$ok = true;
}
else {
$page->add_main_block(new Block("Error with ".html_escape($file['name']),
"Something is not right!"));
$this->theme->display_upload_error("Error with ".html_escape($file['name']),
"Something is not right!");
}
}
return $ok;
}
private function show_result($ok) {
global $page;
if($ok) {
$page->set_mode("redirect");
$page->set_redirect(make_link("index"));
}
else {
$page->set_title("Upload Status");
$page->set_heading("Upload Status");
$page->add_side_block(new NavBlock());
$page->add_main_block(new Block("OK?",
"If there are no errors here, things should be OK \\o/"));
}
}
// }}}
// HTML {{{
private function build_upload_block() {
global $config;
$upload_list = "";
for($i=0; $i<$config->get_int('upload_count', UPLOAD_DEFAULT_COUNT); $i++) {
if($i == 0) $style = ""; // "style='display:visible'";
else $style = "style='display:none'";
$upload_list .= "<input accept='image/jpeg,image/png,image/gif' size='10' ".
"id='data$i' name='data$i' $style onchange=\"showUp('data".($i+1)."')\" type='file'>\n";
}
$max_size = $config->get_int('upload_size', UPLOAD_DEFAULT_MAX_SIZE);
$max_kb = (int)($max_size / 1024);
// <input type='hidden' name='max_file_size' value='$max_size' />
return "
<form enctype='multipart/form-data' action='".make_link("upload")."' method='POST'>
$upload_list
<input id='tagBox' name='tags' type='text' value='tagme' autocomplete='off'>
<input type='submit' value='Post'>
</form>
<div id='upload_completions' style='clear: both;'><small>(Max file size is {$max_kb}KB)</small></div>
";
}
// }}}
}
add_event_listener(new Upload());

47
ext/upload/theme.php Normal file
View file

@ -0,0 +1,47 @@
<?php
class UploadTheme extends Themelet {
public function display_block($page) {
$page->add_block(new Block("Upload", $this->build_upload_block(), "left", 20));
}
public function display_upload_status($page, $ok) {
if($ok) {
$page->set_mode("redirect");
$page->set_redirect(make_link("index"));
}
else {
$page->set_title("Upload Status");
$page->set_heading("Upload Status");
$page->add_block(new NavBlock());
}
}
public function display_upload_error($page, $title, $message) {
$page->add_block(new Block($title, $message));
}
private function build_upload_block() {
global $config;
$upload_list = "";
for($i=0; $i<$config->get_int('upload_count', UPLOAD_DEFAULT_COUNT); $i++) {
if($i == 0) $style = ""; // "style='display:visible'";
else $style = "style='display:none'";
$upload_list .= "<input accept='image/jpeg,image/png,image/gif' size='10' ".
"id='data$i' name='data$i' $style onchange=\"showUp('data".($i+1)."')\" type='file'>\n";
}
$max_size = $config->get_int('upload_size', UPLOAD_DEFAULT_MAX_SIZE);
$max_kb = (int)($max_size / 1024);
// <input type='hidden' name='max_file_size' value='$max_size' />
return "
<form enctype='multipart/form-data' action='".make_link("upload")."' method='POST'>
$upload_list
<input id='tagBox' name='tags' type='text' value='tagme' autocomplete='off'>
<input type='submit' value='Post'>
</form>
<div id='upload_completions' style='clear: both;'><small>(Max file size is {$max_kb}KB)</small></div>
";
}
}
?>

View file

@ -1,56 +1,27 @@
<?php
class Zoom extends Extension {
var $theme;
public function receive_event($event) {
if($this->theme == null) $this->theme = get_theme_object("zoom", "ZoomTheme");
if(is_a($event, 'DisplayingImageEvent')) {
global $page;
$page->add_main_block(new Block(null, $this->make_zoomer()));
global $config;
$this->theme->display_zoomer($page, $config->get_bool("image_zoom", false));
}
if(is_a($event, 'SetupBuildingEvent')) {
$sb = new SetupBlock("Image Zoom");
$sb->add_bool_option("image_zoom", "Zoom by default: ");
$event->panel->add_main_block($sb);
$event->panel->add_block($sb);
}
if(is_a($event, 'ConfigSaveEvent')) {
$event->config->set_bool_from_post("image_zoom");
}
}
private function make_zoomer() {
global $config;
$default = $config->get_bool("image_zoom", false) ? "scale(img);" : "";
return <<<EOD
<script type="text/javascript">
img = byId("main_image");
img.onclick = function() {scale(img);};
msg_div = document.createElement("div");
msg_div.id = "msg_div";
msg_div.appendChild(document.createTextNode("Note: Image has been scaled to fit the screen; click to enlarge"));
msg_div.style.display="none";
img.parentNode.insertBefore(msg_div, img);
orig_width = "";
function scale(img) {
if(img.style.width != "90%") {
origwidth = img.style.width;
img.style.width = "90%";
msg_div.style.display = "block";
}
else {
img.style.width = origwidth;
msg_div.style.display = "none";
}
}
$default
</script>
EOD;
}
}
add_event_listener(new Zoom());
?>

43
ext/zoom/theme.php Normal file
View file

@ -0,0 +1,43 @@
<?php
class ZoomTheme extends Themelet {
public function display_zoomer($page, $zoom_by_default) {
$page->add_block(new Block(null, $this->make_zoomer($zoom_by_default)));
}
private function make_zoomer($zoom_by_default) {
global $config;
$default = $zoom_by_default ? "scale(img);" : "";
return <<<EOD
<script type="text/javascript">
img = byId("main_image");
img.onclick = function() {scale(img);};
msg_div = document.createElement("div");
msg_div.id = "msg_div";
msg_div.appendChild(document.createTextNode("Note: Image has been scaled to fit the screen; click to enlarge"));
msg_div.style.display="none";
img.parentNode.insertBefore(msg_div, img);
orig_width = "";
function scale(img) {
if(img.style.width != "90%") {
origwidth = img.style.width;
img.style.width = "90%";
msg_div.style.display = "block";
}
else {
img.style.width = origwidth;
msg_div.style.display = "none";
}
}
$default
</script>
EOD;
}
}
?>

View file

@ -29,9 +29,13 @@ foreach($files as $filename) {
$database = new Database();
$database->db->fnExecute = 'CountExecs';
$config = new Config();
$_theme = $config->get_string("theme", "default");
require_once "themes/$_theme/page.class.php";
require_once "themes/$_theme/layout.class.php";
require_once "themes/$_theme/themelet.class.php";
$page = new Page();
$user = get_user();
send_event(new InitExtEvent());
send_event(get_page_request());
send_event(get_page_request($page));
$page->display();
?>

View file

@ -40,106 +40,69 @@ Tips
back and forward to other themes all you like.
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
global $config;
$theme_name = $config->get_string('theme');
$base_href = $config->get_string('base_href');
$data_href = $config->get_string('data_href');
$contact_link = $config->get_string('contact_link');
function block_to_html($block, $hidable=false) {
$h = $block->header;
$b = $block->body;
$html = "";
if($hidable) {
$i = str_replace(' ', '_', $h);
if(!is_null($h)) $html .= "\n<h3 id='$i-toggle' onclick=\"toggle('$i')\">$h</h3>\n";
if(!is_null($b)) $html .= "<div id='$i'>$b</div>\n";
}
else {
$i = str_replace(' ', '_', $h);
if(!is_null($h)) $html .= "\n<h3>$h</h3>\n";
if(!is_null($b)) $html .= "<div>$b</div>\n";
}
return $html;
}
$header_html = "";
foreach($this->headers as $line) {
$header_html .= "\t\t$line\n";
}
$sideblock_html = "";
foreach($this->sideblocks as $block) {
$sideblock_html .= block_to_html($block, true);
}
$mainblock_html = "";
foreach($this->mainblocks as $block) {
$mainblock_html .= block_to_html($block, false);
}
$scripts = glob("scripts/*.js");
$script_html = "";
foreach($scripts as $script) {
$script_html .= "\t\t<script src='$data_href/$script' type='text/javascript'></script>\n";
}
if($config->get_bool('debug_enabled')) {
if(function_exists('memory_get_usage')) {
$i_mem = sprintf("%5.2f", ((memory_get_usage()+512)/1024)/1024);
}
else {
$i_mem = "???";
}
if(function_exists('getrusage')) {
$ru = getrusage();
$i_utime = sprintf("%5.2f", ($ru["ru_utime.tv_sec"]*1e6+$ru["ru_utime.tv_usec"])/1000000);
$i_stime = sprintf("%5.2f", ($ru["ru_stime.tv_sec"]*1e6+$ru["ru_stime.tv_usec"])/1000000);
}
else {
$i_utime = "???";
$i_stime = "???";
}
$i_files = count(get_included_files());
global $_execs;
$debug = "<br>Took $i_utime + $i_stime seconds and {$i_mem}MB of RAM";
$debug .= "; Used $i_files files and $_execs queries";
}
else {
$debug = "";
}
global $config;
$version = $config->get_string('version');
$contact = empty($contact_link) ? "" : "<br><a href='$contact_link'>Contact</a>";
if(empty($this->subheading)) {
$subheading = "";
}
else {
$subheading = "<div id='subtitle'>{$this->subheading}</div>";
}
$site_name = $config->get_string('title'); // bzchan: change from normal default to get title for top of page
$front_page = $config->get_string('front_page'); // bzchan: change from normal default to get front page for top of page
// bzchan: CUSTOM LINKS are prepared here, change these to whatever you like
$custom_links = "";
$custom_links .= "<li><a href='".make_link('user')."'>My Account</a></li>";
$custom_links .= "<li><a href='".make_link('index')."'>Posts</a></li>";
$custom_links .= "<li><a href='".make_link('comment/list')."'>Comments</a></li>";
$custom_links .= "<li><a href='".make_link('tags')."'>Tags</a></li>";
class Layout {
public function display_page($page) {
global $config;
$theme_name = $config->get_string('theme');
$base_href = $config->get_string('base_href');
$data_href = $config->get_string('data_href');
$contact_link = $config->get_string('contact_link');
$version = $config->get_string('version');
// bzchan: failed attempt to add heading after title_link (failure was it looked bad)
//if($this->heading==$site_name)$this->heading = '';
//$title_link = "<h1><a href='".make_link($front_page)."'>$site_name</a>/$this->heading</h1>";
$header_html = "";
foreach($page->headers as $line) {
$header_html .= "\t\t$line\n";
}
// bzchan: prepare main title link
$title_link = "<h1><a href='".make_link($front_page)."'>$site_name</a></h1>";
$left_block_html = "";
$main_block_html = "";
print <<<EOD
foreach($page->blocks as $block) {
switch($block->section) {
case "left":
$left_block_html .= $this->block_to_html($block, true);
break;
case "main":
$main_block_html .= $this->block_to_html($block, false);
break;
default:
print "<p>error: {$block->header} using an unknown section ({$block->section})";
break;
}
}
$debug = get_debug_info();
$contact = empty($contact_link) ? "" : "<br><a href='$contact_link'>Contact</a>";
if(empty($this->subheading)) {
$subheading = "";
}
else {
$subheading = "<div id='subtitle'>{$this->subheading}</div>";
}
$site_name = $config->get_string('title'); // bzchan: change from normal default to get title for top of page
$front_page = $config->get_string('front_page'); // bzchan: change from normal default to get front page for top of page
// bzchan: CUSTOM LINKS are prepared here, change these to whatever you like
$custom_links = "";
$custom_links .= "<li><a href='".make_link('user')."'>My Account</a></li>";
$custom_links .= "<li><a href='".make_link('index')."'>Posts</a></li>";
$custom_links .= "<li><a href='".make_link('comment/list')."'>Comments</a></li>";
$custom_links .= "<li><a href='".make_link('tags')."'>Tags</a></li>";
// bzchan: failed attempt to add heading after title_link (failure was it looked bad)
//if($this->heading==$site_name)$this->heading = '';
//$title_link = "<h1><a href='".make_link($front_page)."'>$site_name</a>/$this->heading</h1>";
// bzchan: prepare main title link
$title_link = "<h1><a href='".make_link($front_page)."'>$site_name</a></h1>";
print <<<EOD
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
@ -147,7 +110,6 @@ print <<<EOD
<link rel="stylesheet" href="$data_href/themes/$theme_name/style.css" type="text/css">
$header_html
<script src='$data_href/themes/$theme_name/sidebar.js' type='text/javascript'></script>
$script_html
</head>
<body>
@ -159,8 +121,8 @@ $script_html
</div>
$subheading
<div id="nav">$sideblock_html</div>
<div id="body">$mainblock_html</div>
<div id="nav">$left_block_html</div>
<div id="body">$main_block_html</div>
<div id="footer">
<hr>
@ -174,4 +136,23 @@ $script_html
</body>
</html>
EOD;
}
function block_to_html($block, $hidable=false) {
$h = $block->header;
$b = $block->body;
$html = "";
if($hidable) {
$i = str_replace(' ', '_', $h);
if(!is_null($h)) $html .= "\n<h3 id='$i-toggle' onclick=\"toggle('$i')\">$h</h3>\n";
if(!is_null($b)) $html .= "<div id='$i'>$b</div>\n";
}
else {
$i = str_replace(' ', '_', $h);
if(!is_null($h)) $html .= "\n<h3>$h</h3>\n";
if(!is_null($b)) $html .= "<div>$b</div>\n";
}
return $html;
}
}
?>

View file

@ -1,112 +0,0 @@
<?php
global $config;
$theme_name = $config->get_string('theme');
$base_href = $config->get_string('base_href');
$data_href = $config->get_string('data_href');
$contact_link = $config->get_string('contact_link');
function block_to_html($block, $hidable=false) {
$h = $block->header;
$b = $block->body;
$html = "";
if($hidable) {
$i = str_replace(' ', '_', $h);
if(!is_null($h)) $html .= "\n<h3 id='$i-toggle' onclick=\"toggle('$i')\">$h</h3>\n";
if(!is_null($b)) $html .= "<div id='$i'>$b</div>\n";
}
else {
if(!is_null($h)) $html .= "\n<h3>$h</h3>\n";
if(!is_null($b)) $html .= "<div>$b</div>\n";
}
return $html;
}
$header_html = "";
foreach($this->headers as $line) {
$header_html .= "\t\t$line\n";
}
$sideblock_html = "";
foreach($this->sideblocks as $block) {
$sideblock_html .= block_to_html($block, true);
}
$mainblock_html = "";
foreach($this->mainblocks as $block) {
$mainblock_html .= block_to_html($block, false);
}
$scripts = glob("scripts/*.js");
$script_html = "";
foreach($scripts as $script) {
$script_html .= "\t\t<script src='$data_href/$script' type='text/javascript'></script>\n";
}
if($config->get_bool('debug_enabled')) {
if(function_exists('memory_get_usage')) {
$i_mem = sprintf("%5.2f", ((memory_get_usage()+512)/1024)/1024);
}
else {
$i_mem = "???";
}
if(function_exists('getrusage')) {
$ru = getrusage();
$i_utime = sprintf("%5.2f", ($ru["ru_utime.tv_sec"]*1e6+$ru["ru_utime.tv_usec"])/1000000);
$i_stime = sprintf("%5.2f", ($ru["ru_stime.tv_sec"]*1e6+$ru["ru_stime.tv_usec"])/1000000);
}
else {
$i_utime = "???";
$i_stime = "???";
}
$i_files = count(get_included_files());
global $_execs;
$debug = "<br>Took $i_utime + $i_stime seconds and {$i_mem}MB of RAM";
$debug .= "; Used $i_files files and $_execs queries";
}
else {
$debug = "";
}
global $config;
$version = $config->get_string('version');
$contact = empty($contact_link) ? "" : "<br><a href='$contact_link'>Contact</a>";
if(empty($this->subheading)) {
$subheading = "";
}
else {
$subheading = "<div id='subtitle'>{$this->subheading}</div>";
}
print <<<EOD
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
<title>{$this->title}</title>
<link rel="stylesheet" href="$data_href/themes/$theme_name/style.css" type="text/css">
$header_html
<script src='$data_href/themes/$theme_name/sidebar.js' type='text/javascript'></script>
$script_html
</head>
<body>
<h1>{$this->heading}</h1>
$subheading
<div id="nav">$sideblock_html</div>
<div id="body">$mainblock_html</div>
<div id="footer">
<hr>
Images &copy; their respective owners,
<a href="http://trac.shishnet.org/shimmie2/">$version</a> &copy;
<a href="http://www.shishnet.org/">Shish</a> 2007,
based on the <a href="http://trac.shishnet.org/shimmie2/wiki/DanbooruRipoff">Danbooru</a> concept.
$debug
$contact
</div>
</body>
</html>
EOD;
?>

View file

@ -0,0 +1,92 @@
<?php
class Layout {
function display_page($page) {
global $config;
$theme_name = $config->get_string('theme');
$base_href = $config->get_string('base_href');
$data_href = $config->get_string('data_href');
$contact_link = $config->get_string('contact_link');
$version = $config->get_string('version');
$header_html = "";
foreach($page->headers as $line) {
$header_html .= "\t\t$line\n";
}
$left_block_html = "";
$main_block_html = "";
foreach($page->blocks as $block) {
switch($block->section) {
case "left":
$left_block_html .= $this->block_to_html($block, true);
break;
case "main":
$main_block_html .= $this->block_to_html($block, false);
break;
default:
print "<p>error: {$block->header} using an unknown section ({$block->section})";
break;
}
}
$debug = get_debug_info();
$contact = empty($contact_link) ? "" : "<br><a href='$contact_link'>Contact</a>";
if(empty($this->subheading)) {
$subheading = "";
}
else {
$subheading = "<div id='subtitle'>{$this->subheading}</div>";
}
print <<<EOD
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
<title>{$page->title}</title>
<link rel="stylesheet" href="$data_href/themes/$theme_name/style.css" type="text/css">
$header_html
<script src='$data_href/themes/$theme_name/sidebar.js' type='text/javascript'></script>
</head>
<body>
<h1>{$page->heading}</h1>
$subheading
<div id="nav">$left_block_html</div>
<div id="body">$main_block_html</div>
<div id="footer">
<hr>
Images &copy; their respective owners,
<a href="http://trac.shishnet.org/shimmie2/">$version</a> &copy;
<a href="http://www.shishnet.org/">Shish</a> 2007,
based on the <a href="http://trac.shishnet.org/shimmie2/wiki/DanbooruRipoff">Danbooru</a> concept.
$debug
$contact
</div>
</body>
</html>
EOD;
}
function block_to_html($block, $hidable=false) {
$h = $block->header;
$b = $block->body;
$html = "";
if($hidable) {
$i = str_replace(' ', '_', $h);
if(!is_null($h)) $html .= "\n<h3 id='$i-toggle' onclick=\"toggle('$i')\">$h</h3>\n";
if(!is_null($b)) $html .= "<div id='$i'>$b</div>\n";
}
else {
if(!is_null($h)) $html .= "\n<h3>$h</h3>\n";
if(!is_null($b)) $html .= "<div>$b</div>\n";
}
return $html;
}
}
?>

View file

@ -0,0 +1,6 @@
<?php
class Page extends GenericPage {
// no changes from default
}
?>

View file

@ -0,0 +1,11 @@
<?php
class Themelet {
public function display_error($page, $title, $message) {
$page->set_title($title);
$page->set_heading($title);
$page->add_side_block(new NavBlock());
$page->add_main_block(new Block("Error", $message));
}
}
?>