Merge branch 'master' of github.com:shish/shimmie2

This commit is contained in:
Shish 2012-03-10 19:13:42 +00:00
commit 89efc3b524
23 changed files with 306 additions and 275 deletions

View file

@ -35,6 +35,14 @@ class AdminBuildingEvent extends Event {
}
}
class AdminActionEvent extends Event {
var $action;
var $redirect = true;
public function __construct(/*string*/ $action) {
$this->action = $action;
}
}
class AdminPage extends Extension {
public function onPageRequest(PageRequestEvent $event) {
global $page, $user;
@ -44,61 +52,31 @@ class AdminPage extends Extension {
$this->theme->display_permission_denied();
}
else {
send_event(new AdminBuildingEvent($page));
}
}
if($event->page_matches("admin_utils")) {
if($user->is_admin() && $user->check_auth_token()) {
log_info("admin", "Util: {$_POST['action']}");
set_time_limit(0);
$redirect = false;
switch($_POST['action']) {
case 'delete by query':
$this->delete_by_query($_POST['query']);
$redirect = true;
break;
case 'lowercase all tags':
$this->lowercase_all_tags();
$redirect = true;
break;
case 'recount tag use':
$this->recount_tag_use();
$redirect = true;
break;
case 'purge unused tags':
$this->purge_unused_tags();
$redirect = true;
break;
case 'convert to innodb':
$this->convert_to_innodb();
$redirect = true;
break;
case 'database dump':
$this->dbdump($page);
break;
case 'reset image ids':
$this->reset_imageids();
$redirect = true;
break;
case 'image dump':
$this->imgdump($page);
break;
if($event->count_args() == 0) {
send_event(new AdminBuildingEvent($page));
}
else {
$action = $event->get_arg(0);
$aae = new AdminActionEvent($action);
if($redirect) {
$page->set_mode("redirect");
$page->set_redirect(make_link("admin"));
if($user->check_auth_token()) {
log_info("admin", "Util: $action");
set_time_limit(0);
send_event($aae);
}
if($aae->redirect) {
$page->set_mode("redirect");
$page->set_redirect(make_link("admin"));
}
}
}
}
}
public function onAdminBuilding(AdminBuildingEvent $event) {
global $page;
$this->theme->display_page($page);
$this->theme->display_form($page);
$this->theme->display_page();
$this->theme->display_form();
}
public function onUserBlockBuilding(UserBlockBuildingEvent $event) {
@ -108,17 +86,38 @@ class AdminPage extends Extension {
}
}
private function delete_by_query(/*array(string)*/ $query) {
public function onAdminAction(AdminActionEvent $event) {
$action = $event->action;
if(method_exists($this, $action)) {
$event->redirect = $this->$action();
}
}
public function onPostListBuilding(PostListBuildingEvent $event) {
global $user;
if($user->is_admin() && !empty($event->search_terms)) {
$this->theme->display_dbq(implode(" ", $event->search_terms));
}
}
private function delete_by_query() {
global $page, $user;
$query = $_POST['query'];
assert(strlen($query) > 1);
foreach(Image::find_images(0, 1000000, Tag::explode($query)) as $image) {
send_event(new ImageDeletionEvent($image));
}
$page->set_mode("redirect");
$page->set_redirect(make_link("post/list"));
return false;
}
private function lowercase_all_tags() {
global $database;
$database->execute("UPDATE tags SET tag=lower(tag)");
return true;
}
private function recount_tag_use() {
@ -128,16 +127,21 @@ class AdminPage extends Extension {
SET count = COALESCE(
(SELECT COUNT(image_id) FROM image_tags WHERE tag_id=tags.id GROUP BY tag_id),
0
)");
)
");
return true;
}
private function purge_unused_tags() {
global $database;
$this->recount_tag_use();
$database->Execute("DELETE FROM tags WHERE count=0");
return true;
}
private function dbdump(Page $page) {
private function dump_database() {
global $page;
$matches = array();
preg_match("#^(?P<proto>\w+)\:(?:user=(?P<user>\w+)(?:;|$)|password=(?P<password>\w+)(?:;|$)|host=(?P<host>[\w\.\-]+)(?:;|$)|dbname=(?P<dbname>[\w_]+)(?:;|$))+#", DATABASE_DSN, $matches);
$software = $matches['proto'];
@ -157,6 +161,8 @@ class AdminPage extends Extension {
$page->set_type("application/x-unknown");
$page->set_filename('shimmie-'.date('Ymd').'.sql');
$page->set_data(shell_exec($cmd));
return false;
}
private function check_for_orphanned_images() {
@ -169,23 +175,29 @@ class AdminPage extends Extension {
}
}
}
return true;
}
/*
private function convert_to_innodb() {
global $database;
if($database->engine->name == "mysql") {
$tables = $database->db->MetaTables();
foreach($tables as $table) {
log_info("upgrade", "converting $table to innodb");
$database->execute("ALTER TABLE $table TYPE=INNODB");
}
if($database->engine->name != "mysql") return;
$tables = $database->db->MetaTables();
foreach($tables as $table) {
log_info("upgrade", "converting $table to innodb");
$database->execute("ALTER TABLE $table TYPE=INNODB");
}
return true;
}
*/
private function reset_imageids() {
private function reset_image_ids() {
global $database;
if($database->engine->name != "mysql") return;
//This might be a bit laggy on boards with lots of images (?)
//Seems to work fine with 1.2k~ images though.
$i = 0;
@ -221,15 +233,17 @@ class AdminPage extends Extension {
}
$count = (count($image)) + 1;
$database->execute("ALTER TABLE images AUTO_INCREMENT=".$count);
return true;
}
private function imgdump(Page $page) {
global $database;
private function download_all_images() {
global $database, $page;
$zip = new ZipArchive;
$images = $database->get_all("SELECT * FROM images");
$filename = 'imgdump-'.date('Ymd').'.zip';
if($zip->open($filename, 1 ? ZIPARCHIVE::OVERWRITE:ZIPARCHIVE::CREATE)===TRUE){
if($zip->open($filename, 1 ? ZIPARCHIVE::OVERWRITE:ZIPARCHIVE::CREATE) === TRUE){
foreach($images as $img){
$hash = $img["hash"];
preg_match("^[A-Za-z0-9]{2}^", $hash, $matches);
@ -241,9 +255,11 @@ class AdminPage extends Extension {
}
$zip->close();
}
$page->set_mode("redirect");
$page->set_redirect(make_link($filename)); //Fairly sure there is better way to do this..
//TODO: Delete file after downloaded?
return false; // we do want a redirect, but a manual one
}
}
?>

18
contrib/admin/style.css Normal file
View file

@ -0,0 +1,18 @@
.admin {
padding: 4px;
border-radius: 4px;
background: green;
margin: 6px;
width: 200px;
display: inline-block;
}
.admin.protected {
background: red;
}
.admin INPUT[type="submit"] {
width: 100%;
}
.admin.protected INPUT[type="submit"] {
width: 90%;
}

View file

@ -4,81 +4,61 @@ class AdminPageTheme extends Themelet {
/*
* Show the basics of a page, for other extensions to add to
*/
public function display_page(Page $page) {
public function display_page() {
global $page;
$page->set_title("Admin Tools");
$page->set_heading("Admin Tools");
$page->add_block(new NavBlock());
}
protected function button(/*string*/ $name, /*string*/ $action, /*boolean*/ $protected=false) {
$c_protected = $protected ? " protected" : "";
$html = make_form(make_link("admin/$action"), "POST", false, false, false, "admin$c_protected");
if($protected) {
$html .= "<input type='checkbox' onclick='$(\"#$action\").attr(\"disabled\", !$(this).is(\":checked\"))'>";
$html .= "<input type='submit' id='$action' value='$name' disabled='true'>";
}
else {
$html .= "<input type='submit' id='$action' value='$name'>";
}
$html .= "</form>\n";
return $html;
}
/*
* Show a form which links to admin_utils with POST[action] set to one of:
* 'lowercase all tags'
* 'recount tag use'
* 'purge unused tags'
*/
public function display_form(Page $page) {
global $user;
public function display_form() {
global $page, $database;
$html = '
<script type="text/javascript">
function imgidconfirm(){
if(document.getElementById("misc").selectedIndex == 4){
if(confirm("This function WILL break any bookmarks & links.\n The event log will also not be updated with new ids. \n Are you sure you wish to continue?")){
return true;
}else{
return false;
}
}
}
</script>
'.make_form(make_link("admin_utils"),"post", false, false, "return imgidconfirm()")."
<select name='action' id='misc'>
<option value='lowercase all tags'>All tags to lowercase</option>
<option value='recount tag use'>Recount tag use</option>
<option value='purge unused tags'>Purge unused tags</option>
<option value='database dump'>Download database contents</option>
<option value='reset image ids'>Reset image ids</option>
<option value='image dump'>Download all images</option>
<!--<option value='convert to innodb'>Convert database to InnoDB (MySQL only)</option>-->
</select>
<input type='submit' value='Go'>
</form>
";
$html = "";
$html .= $this->button("All tags to lowercase", "lowercase_all_tags", true);
$html .= $this->button("Recount tag use", "recount_tag_user", false);
$html .= $this->button("Purge unused tags", "purge_unused_tags", true);
$html .= $this->button("Download all images", "image_dump", false);
if($database->engine->name == "mysql") {
$html .= $this->button("Download database contents", "database_dump", false);
$html .= $this->button("Reset image IDs", "reset_image_ids", true);
}
$page->add_block(new Block("Misc Admin Tools", $html));
/* First check
Requires you to click the checkbox to enable the delete by query form */
$dbqcheck = 'javascript:$(function() {
if($("#dbqcheck:checked").length != 0){
$("#dbqtags").attr("disabled", false);
$("#dbqsubmit").attr("disabled", false);
}else{
$("#dbqtags").attr("disabled", true);
$("#dbqsubmit").attr("disabled", true);
}
});';
/* Second check
Requires you to confirm the deletion by clicking ok. */
$html = "
<script type='text/javascript'>
function checkform(){
if(confirm('Are you sure you wish to delete all images using these tags?')){
return true;
}else{
return false;
}
}
</script>"
.make_form(make_link("admin_utils"),"post",false,false,"return checkform()")."
<input type='checkbox' id='dbqcheck' name='action' onclick='$dbqcheck'>
<input type='hidden' name='action' value='delete by query'>
<input type='text' id='dbqtags' disabled='true' name='query'>
<input type='submit' id='dbqsubmit' disabled='true' value='Go'>
}
public function display_dbq($terms) {
global $page;
$h_terms = html_escape($terms);
$html = make_form(make_link("admin/delete_by_query"), "POST") . "
<input type='button' class='shm-unlocker' data-unlock-id='dbqsubmit' value='Unlock'>
<input type='hidden' name='query' value='$h_terms'>
<input type='submit' id='dbqsubmit' disabled='true' value='Delete All These Images'>
</form>
";
$page->add_block(new Block("Delete by Query", $html));
$page->add_block(new Block("List Controls", $html, "left"));
}
}
?>

View file

@ -4,19 +4,27 @@ class BlocksTest extends SCoreWebTestCase {
$this->log_in_as_admin();
$this->get_page("setup");
$this->set_field("_config_blocks_text", "badgers");
$this->set_field("_config_blocks_text", "
Title: some text
Area: main
Priority: 100
Pages: *
waffles
");
$this->click("Save Settings");
$this->get_page("post/list");
$this->assert_text("badgers");
$this->assert_text("some text");
$this->assert_text("waffles");
$this->get_page("setup");
$this->set_field("_config_blocks_text", "");
$this->click("Save Settings");
$this->get_page("post/list");
$this->assert_no_text("Note");
$this->assert_no_text("badgers");
$this->assert_no_text("some text");
$this->assert_no_text("waffles");
$this->log_out();
}

View file

@ -0,0 +1,9 @@
<?php
class BookmarksTest extends ShimmieWebTestCase {
function testBookmarks() {
$this->get_page("bookmark/add");
$this->get_page("bookmark/remove");
}
}
?>

View file

@ -13,14 +13,21 @@ class FeaturedTest extends ShimmieWebTestCase {
$this->click("Feature This");
$this->get_page("post/list");
$this->assert_text("Featured Image");
# FIXME: test changing from one feature to another
$this->get_page("featured_image/download");
$this->assert_response(200);
$this->get_page("featured_image/view");
$this->assert_response(200);
$this->delete_image($image_id);
$this->log_out();
# after deletion, there should be no feature
$this->get_page("post/list");
$this->assert_no_text("Featured Image");
# FIXME: test changing from one feature to another
}
}
?>

View file

@ -2,10 +2,11 @@
class IcoHandlerTest extends ShimmieWebTestCase {
function testPixelHander() {
$this->log_in_as_user();
$image_id = $this->post_image("favicon.ico", "shimmie favicon");
$image_id = $this->post_image("lib/static/favicon.ico", "shimmie favicon");
$this->assert_response(302);
$this->log_out();
$raw = $this->get_page("post/view/$image_id"); // test for no crash
$raw = $this->get_page("get_ico/$image_id"); // test for no crash
$this->log_in_as_admin();

View file

@ -0,0 +1,37 @@
<?php
class HashBanTest extends ShimmieWebTestCase {
function testBan() {
$this->log_in_as_user();
$image_id = $this->post_image("ext/simpletest/data/pbx_screenshot.jpg", "pbx");
$this->log_out();
$this->log_in_as_admin();
$this->get_page("post/view/$image_id");
$this->click("Ban and Delete");
$this->log_out();
$this->log_in_as_user();
$this->get_page("post/view/$image_id");
$this->assert_response(404);
$image_id = $this->post_image("ext/simpletest/data/pbx_screenshot.jpg", "pbx");
$this->get_page("post/view/$image_id");
$this->assert_response(404);
$this->log_out();
$this->log_in_as_admin();
$this->get_page("image_hash_ban/list/1");
$this->click("Remove");
$this->log_out();
$this->log_in_as_user();
$image_id = $this->post_image("ext/simpletest/data/pbx_screenshot.jpg", "pbx");
$this->get_page("post/view/$image_id");
$this->assert_response(200);
$this->log_out();
$this->log_in_as_admin();
$this->delete_image($image_id);
$this->log_out();
}
}
?>

View file

@ -2,6 +2,7 @@
class LogDatabaseTest extends SCoreWebTestCase {
function testLog() {
$this->log_in_as_admin();
$this->get_page("log/view");
$this->log_out();
}
}

9
contrib/oekaki/test.php Normal file
View file

@ -0,0 +1,9 @@
<?php
class OekakiTest extends SCoreWebTestCase {
function testLog() {
$this->log_in_as_user();
$this->get_page("oekaki/create");
$this->log_out();
}
}
?>

View file

@ -19,7 +19,7 @@ class RandomTest extends ShimmieWebTestCase {
$this->log_out();
}
function tesPostListBlock() {
function testPostListBlock() {
$this->log_in_as_admin();
$this->get_page("setup");
$this->set_field("_config_show_random_block", true);

View file

@ -37,7 +37,7 @@ class _SafeImage {
class ShimmieApi extends Extension {
public function onPageRequest(PageRequestEvent $event) {
global $database, $page;
global $database, $page, $user;
if($event->page_matches("api/shimmie")) {
$page->set_mode("data");
@ -55,7 +55,7 @@ class ShimmieApi extends Extension {
"SELECT tag FROM tags WHERE tag LIKE ?",
array($arg."%"));
}
elseif(isset($_GET['id'])){
elseif(isset($_GET['tag'])){
$all = $database->get_all(
"SELECT tag FROM tags WHERE tag LIKE ?",
array($_GET['tag']."%"));
@ -76,9 +76,7 @@ class ShimmieApi extends Extension {
elseif(isset($_GET['id'])){
$image = Image::by_id(int_escape($_GET['id']));
}
else{
$image = Image::by_id(int_escape("1")); //Default to id=1
}
// FIXME: handle null image
$image->get_tag_array(); // tag data isn't loaded into the object until necessary
$safe_image = new _SafeImage($image);
$page->set_data(json_encode($safe_image));
@ -98,29 +96,24 @@ class ShimmieApi extends Extension {
}
if($event->page_matches("api/shimmie/get_user")) {
if(isset($_GET['name'])){
$all = $database->get_all(
"SELECT id,name,joindate,class FROM users WHERE name=?",
array($_GET['name']));
$query = $user->id;
if($event->count_args() == 1) {
$query = $event->get_arg(0);
}
if(isset($_GET['name'])) {
$query = $_GET['name'];
}
if(isset($_GET['id'])) {
$query = $_GET['id'];
}
if(isset($_GET['id'])){
$all = $database->get_all(
"SELECT id,name,joindate,class FROM users WHERE id=?",
array($_GET['id']));
}
$all = $database->get_row(
"SELECT id,name,joindate,class FROM users WHERE name=? OR id=?",
array($_GET['name'], int_escape($_GET['id'])));
if(!isset($_GET['id']) && !isset($_GET['name'])){
$all = $database->get_all(
"SELECT id,name,joindate,class FROM users WHERE id=?",
array("2")); //In 99% of cases, this will be the admin.
}
$all = $all[0];
//FIXME?: For some weird reason, get_all seems to return twice. Unsetting second value to make things look nice..
// - it returns data as eg array(0=>1234, 'id'=>1234, 1=>'bob', 'name'=>bob, ...);
for($i=0; $i<4; $i++) unset($all[$i]);
/*TODO: Might be worth making it possible just to get a certain stat (Using &stat=uploadcount or something)
This would lessen strain on DB? */
$all['uploadcount'] = Image::count_images(array("user_id=".$all['id']));
$all['uploadperday'] = sprintf("%.1f", ($all['uploadcount'] / (((time() - strtotime($all['joindate'])) / 86400) + 1)));
$all['commentcount'] = $database->get_one(

View file

@ -0,0 +1,29 @@
<?php
class ShimmieApiTest extends ShimmieWebTestCase {
function testAPI() {
$this->log_in_as_user();
$image_id = $this->post_image("ext/simpletest/data/pbx_screenshot.jpg", "pbx");
$this->get_page("api/shimmie/get_tags");
$this->get_page("api/shimmie/get_tags/pb");
$this->get_page("api/shimmie/get_tags?tag=pb");
$this->get_page("api/shimmie/get_image/$image_id");
$this->get_page("api/shimmie/get_image?id=$image_id");
$this->get_page("api/shimmie/find_images");
$this->get_page("api/shimmie/find_images/pbx");
$this->get_page("api/shimmie/find_images/pbx/1");
$this->get_page("api/shimmie/get_user/demo");
$this->get_page("api/shimmie/get_user?name=demo");
$this->get_page("api/shimmie/get_user?id=2");
// FIXME: test unspecified / bad values
// FIXME: test that json is encoded properly
$this->log_out();
$this->log_in_as_admin();
$this->delete_image($image_id);
$this->log_out();
}
}
?>

View file

@ -13,8 +13,8 @@ class TagHistoryTest extends ShimmieWebTestCase {
$this->click("Revert To");
$this->assert_title("Image $image_id: pbx");
$this->get_page("tag_history");
$this->click("Global Tag History");
$this->get_page("tag_history/all/1");
$this->assert_title("Global Tag History");
$this->delete_image($image_id);
$this->log_out();

View file

@ -7,19 +7,19 @@ class TwitterSocTest extends SCoreWebTestCase {
$this->set_field("_config_twitter_soc_username", "shish2k");
$this->click("Save Settings");
/*
$this->get_page("post/list");
$this->assert_text("Note");
$this->assert_text("kittens");
$this->assert_text("Tweets");
/*
$this->assert_text("kittens"); // this is loaded with javascript
*/
$this->get_page("setup");
$this->set_field("_config_twitter_soc_username", "");
$this->click("Save Settings");
/*
$this->get_page("post/list");
$this->assert_no_text("Note");
$this->assert_no_text("Tweets");
/*
$this->assert_no_text("kittens");
*/

View file

@ -56,6 +56,7 @@ class Image {
$this->$name = $value; // hax
}
$this->posted_timestamp = strtotime($this->posted); // pray
$this->locked = undb_bool($this->locked);
assert(is_numeric($this->id));
assert(is_numeric($this->height));
@ -411,8 +412,9 @@ class Image {
* @retval bool
*/
public function is_locked() {
return ($this->locked === true || $this->locked == "Y" || $this->locked == "t");
return $this->locked;
}
public function set_locked($tf) {
global $database;
$ln = $tf ? "Y" : "N";

View file

@ -172,15 +172,6 @@ function isValidDate($date) {
return false;
}
/**
* Return a pluraliser if necessary
*
* @retval string
*/
function plural($num, $single_form="", $plural_form="s") {
return ($num == 1) ? $single_form : $plural_form;
}
/**
* Give a HTML string which shows an IP (if the user is allowed to see IPs),
* and a link to ban that IP (if the user is allowed to ban IPs)
@ -198,19 +189,6 @@ function show_ip($ip, $ban_reason) {
return $ip;
}
/**
* Turn an IP address into a colour, for easily spotting samefags
*
* NOTE: this should only be shown to admins, as it can be reversed
* to get an original IP address
*/
function ip2color($ip) {
$b = explode(".", $ip);
#return sprintf("#%02x%02x%02x", $b[0]/2, $b[1]/2, $b[2]/2);
return sprintf("hsl(%d, %d%%, %d%%)", $b[3]*360/256, $b[2]*100/256, $b[1]*100/256/2);
}
/**
* Different databases have different ways to represent booleans; this
* will try and standardise them
@ -361,27 +339,6 @@ function make_form($target, $method="POST", $multipart=False, $form_id="", $onsu
return '<form action="'.$target.'" method="'.$method.'" '.$extra.'>'.$auth;
}
/**
* Make a link to a static file in the current theme's
* directory
*/
function theme_file($filepath) {
global $config;
$theme = $config->get_string("theme","default");
return make_link('themes/'.$theme.'/'.$filepath);
}
function hsl_rainbow() {
$ct = Array();
$s = 100; $l = 25; for($h= 0; $h<360; $h+=60) {$ct[] = "hsl($h, $s%, $l%);";}
$s = 100; $l = 50; for($h= 0; $h<360; $h+=60) {$ct[] = "hsl($h, $s%, $l%);";}
$s = 50; $l = 25; for($h= 0; $h<360; $h+=60) {$ct[] = "hsl($h, $s%, $l%);";}
$s = 100; $l = 25; for($h=30; $h<360; $h+=60) {$ct[] = "hsl($h, $s%, $l%);";}
$s = 100; $l = 50; for($h=30; $h<360; $h+=60) {$ct[] = "hsl($h, $s%, $l%);";}
$s = 50; $l = 25; for($h=30; $h<360; $h+=60) {$ct[] = "hsl($h, $s%, $l%);";}
return $ct;
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
* CAPTCHA abstraction *
@ -886,23 +843,6 @@ function full_copy($source, $target) {
}
}
/**
* @private
*/
function weighted_random($weights) {
$total = 0;
foreach($weights as $k => $w) {
$total += $w;
}
$r = mt_rand(0, $total);
foreach($weights as $k => $w) {
$r -= $w;
if($r <= 0) {
return $k;
}
}
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
* Event API *

View file

@ -70,7 +70,7 @@ class CommentList extends Extension {
$config->set_default_int('comment_count', 5);
$config->set_default_bool('comment_captcha', false);
if($config->get_int("ext_comments_version") < 2) {
if($config->get_int("ext_comments_version") < 3) {
// shortcut to latest
if($config->get_int("ext_comments_version") < 1) {
$database->create_table("comments", "
@ -84,14 +84,14 @@ class CommentList extends Extension {
INDEX (owner_ip),
INDEX (posted),
FOREIGN KEY (image_id) REFERENCES images(id) ON DELETE CASCADE,
FOREIGN KEY (owner_id) REFERENCES users(id) ON DELETE CASCADE
FOREIGN KEY (owner_id) REFERENCES users(id) ON DELETE RESTRICT
");
$config->set_int("ext_comments_version", 2);
$config->set_int("ext_comments_version", 3);
}
// ===
// the whole history
if($config->get_int("ext_comments_version") < 1) {
$database->Execute("CREATE TABLE comments (
$database->create_table("comments", "
id {$database->engine->auto_increment},
image_id INTEGER NOT NULL,
owner_id INTEGER NOT NULL,
@ -99,7 +99,7 @@ class CommentList extends Extension {
posted DATETIME DEFAULT NULL,
comment TEXT NOT NULL,
INDEX (image_id)
) {$database->engine->create_table_extras}");
");
$config->set_int("ext_comments_version", 1);
}
@ -108,6 +108,14 @@ class CommentList extends Extension {
$database->Execute("CREATE INDEX comments_posted ON comments(posted)");
$config->set_int("ext_comments_version", 2);
}
if($config->get_int("ext_comments_version") == 2) {
$config->set_int("ext_comments_version", 3);
$database->Execute("ALTER TABLE comments ADD CONSTRAINT foreign_comments_image_id FOREIGN KEY (image_id) REFERENCES images(id) ON DELETE CASCADE");
$database->Execute("ALTER TABLE comments ADD CONSTRAINT foreign_comments_owner_id FOREIGN KEY (owner_id) REFERENCES users(id) ON DELETE RESTRICT");
}
// FIXME: add foreign keys, bump to v3
}
}
@ -186,13 +194,6 @@ class CommentList extends Extension {
);
}
public function onImageDeletion(ImageDeletionEvent $event) {
global $database;
$image_id = $event->image->id;
$database->Execute("DELETE FROM comments WHERE image_id=:image_id", array("image_id"=>$image_id));
log_info("comment", "Deleting all comments for Image #$image_id");
}
// TODO: split akismet into a separate class, which can veto the event
public function onCommentPosting(CommentPostingEvent $event) {
$this->add_comment_wrapper($event->image_id, $event->user, $event->comment);

View file

@ -5,6 +5,9 @@ class Handle404Test extends SCoreWebTestCase {
$this->assert_response(404);
$this->assert_title('404');
$this->assert_text("No handler could be found for the page 'not/a/page'");
$this->get_page('favicon.ico');
$this->assert_response(200);
}
}
?>

View file

@ -29,10 +29,6 @@ class SetupBuildingEvent extends Event {
public function SetupBuildingEvent(SetupPanel $panel) {
$this->panel = $panel;
}
public function get_panel() {
return $this->panel;
}
}
// }}}
/* SetupPanel {{{

View file

@ -87,7 +87,17 @@ class SetupTheme extends Themelet {
}
protected function sb_to_html(SetupBlock $block) {
return "<div class='setupblock'><b>{$block->header}</b><br>{$block->body}</div>\n";
$h = $block->header;
$b = $block->body;
$i = preg_replace('/[^a-zA-Z0-9]/', '_', $h) . "-setup";
$html = "
<div class='setupblock brr'>
<b class='shm-toggler' data-toggle-id='$i'>$h</b>
<br><div id='$i'>$b</div>
</div>
<!-- cancel border -->
";
return $html;
}
}
?>

View file

@ -76,6 +76,15 @@ $(document).ready(function() {
})
});
$(".shm-unlocker").each(function(idx, elm) {
var tid = $(elm).data("unlock-id");
var tob = $("#"+tid);
$(elm).click(function(e) {
$(elm).attr("disabled", true);
tob.attr("disabled", false);
});
});
if(document.location.hash.length > 3) {
query = document.location.hash.substring(1);
a = document.getElementById("prevlink");

View file

@ -1,38 +0,0 @@
<?php
/**
* A customised version of the Setup theme
*/
class CustomSetupTheme extends SetupTheme {
protected function sb_to_html(SetupBlock $block) {
$h = $block->header;
$b = $block->body;
$i = preg_replace('/[^a-zA-Z0-9]/', '_', $h) . "-setup";
$html = "
<script type='text/javascript'><!--
$(document).ready(function() {
$(\"#$i-toggle\").click(function() {
$(\"#$i\").slideToggle(\"slow\", function() {
if($(\"#$i\").is(\":hidden\")) {
$.cookie(\"$i-hidden\", 'true', {path: '/'});
}
else {
$.cookie(\"$i-hidden\", 'false', {path: '/'});
}
});
});
if($.cookie(\"$i-hidden\") == 'true') {
$(\"#$i\").hide();
}
});
//--></script>
<div class='setupblock brr'>
<b id='$i-toggle'>$h</b>
<br><div id='$i'>$b</div>
</div>
<!-- cancel border -->
";
return $html;
}
}
?>