Merge branch 'master' of github.com:shish/shimmie2
This commit is contained in:
commit
89efc3b524
23 changed files with 306 additions and 275 deletions
|
@ -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 {
|
||||
if($event->count_args() == 0) {
|
||||
send_event(new AdminBuildingEvent($page));
|
||||
}
|
||||
}
|
||||
else {
|
||||
$action = $event->get_arg(0);
|
||||
$aae = new AdminActionEvent($action);
|
||||
|
||||
if($event->page_matches("admin_utils")) {
|
||||
if($user->is_admin() && $user->check_auth_token()) {
|
||||
log_info("admin", "Util: {$_POST['action']}");
|
||||
if($user->check_auth_token()) {
|
||||
log_info("admin", "Util: $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;
|
||||
send_event($aae);
|
||||
}
|
||||
|
||||
if($redirect) {
|
||||
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") {
|
||||
|
||||
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
18
contrib/admin/style.css
Normal 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%;
|
||||
}
|
||||
|
|
@ -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;
|
||||
$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);
|
||||
}
|
||||
}
|
||||
}
|
||||
</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>
|
||||
";
|
||||
$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>"
|
||||
public function display_dbq($terms) {
|
||||
global $page;
|
||||
|
||||
.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'>
|
||||
$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"));
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
9
contrib/bookmarks/test.php
Normal file
9
contrib/bookmarks/test.php
Normal file
|
@ -0,0 +1,9 @@
|
|||
|
||||
<?php
|
||||
class BookmarksTest extends ShimmieWebTestCase {
|
||||
function testBookmarks() {
|
||||
$this->get_page("bookmark/add");
|
||||
$this->get_page("bookmark/remove");
|
||||
}
|
||||
}
|
||||
?>
|
|
@ -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
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
|
|
@ -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();
|
||||
|
|
37
contrib/image_hash_ban/test.php
Normal file
37
contrib/image_hash_ban/test.php
Normal 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();
|
||||
}
|
||||
}
|
||||
?>
|
|
@ -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
9
contrib/oekaki/test.php
Normal 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();
|
||||
}
|
||||
}
|
||||
?>
|
|
@ -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);
|
||||
|
|
|
@ -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(
|
||||
|
|
29
contrib/shimmie_api/test.php
Normal file
29
contrib/shimmie_api/test.php
Normal 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();
|
||||
}
|
||||
}
|
||||
?>
|
|
@ -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();
|
||||
|
|
|
@ -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");
|
||||
*/
|
||||
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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 *
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
|
|
@ -29,10 +29,6 @@ class SetupBuildingEvent extends Event {
|
|||
public function SetupBuildingEvent(SetupPanel $panel) {
|
||||
$this->panel = $panel;
|
||||
}
|
||||
|
||||
public function get_panel() {
|
||||
return $this->panel;
|
||||
}
|
||||
}
|
||||
// }}}
|
||||
/* SetupPanel {{{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
?>
|
Reference in a new issue