fix a lot of tests

This commit is contained in:
Shish 2020-01-29 20:22:50 +00:00
parent 86d93b2cc2
commit 4e57e04ddf
42 changed files with 660 additions and 677 deletions

View file

@ -375,10 +375,14 @@ abstract class DataHandlerExtension extends Extension
// even more hax..
$event->metadata['tags'] = $existing->get_tag_list();
$image = $this->create_image_from_data(warehouse_path(Image::IMAGE_DIR, $event->metadata['hash']), $event->metadata);
if (is_null($image)) {
throw new UploadException("Data handler failed to create image object from data");
}
try {
send_event(new MediaCheckPropertiesEvent($image));
} catch (MediaException $e) {
throw new UploadException("Unable to scan media properties: ".$e->getMessage());
}
$ire = send_event(new ImageReplaceEvent($image_id, $image));
$event->image_id = $image_id;
@ -387,6 +391,12 @@ abstract class DataHandlerExtension extends Extension
if (is_null($image)) {
throw new UploadException("Data handler failed to create image object from data");
}
try {
send_event(new MediaCheckPropertiesEvent($image));
} catch (MediaException $e) {
throw new UploadException("Unable to scan media properties: ".$e->getMessage());
}
$iae = send_event(new ImageAdditionEvent($image));
$event->image_id = $iae->image->id;
$event->merged = $iae->merged;
@ -404,6 +414,7 @@ abstract class DataHandlerExtension extends Extension
}
}
} elseif ($supported_ext && !$check_contents) {
// We DO support this extension - but the file looks corrupt
throw new UploadException("Invalid or corrupted file");
}
}
@ -435,15 +446,6 @@ abstract class DataHandlerExtension extends Extension
}
}
/*
public function onSetupBuilding(SetupBuildingEvent $event) {
$sb = $this->setup();
if($sb) $event->panel->add_block($sb);
}
protected function setup() {}
*/
abstract protected function supported_ext(string $ext): bool;
abstract protected function check_contents(string $tmpname): bool;
abstract protected function create_image_from_data(string $filename, array $metadata);

View file

@ -60,12 +60,18 @@ class Image
/** @var boolean */
public $video = null;
/** @var boolean */
public $image = null;
/** @var boolean */
public $audio = null;
/** @var int */
public $length = null;
public static $bool_props = ["locked", "lossless", "video", "audio"];
public static $int_props = ["id", "owner_id", "height", "width", "filesize", "length"];
/**
* One will very rarely construct an image directly, more common
* would be to use Image::by_id, Image::by_hash, etc.
@ -78,9 +84,11 @@ class Image
$name = str_replace("images.", "", $name);
// hax, this is likely the cause of much scrutinizer-ci complaints.
if (in_array($name, ["locked", "lossless", "video", "audio"])) {
if (is_null($value)) {
$this->$name = null;
} elseif (in_array($name, self::$bool_props)) {
$this->$name = bool_escape((string)$value);
} elseif (in_array($name, ["id", "owner_id", "height", "width", "filesize", "length"])) {
} elseif (in_array($name, self::$int_props)) {
$this->$name = int_escape((string)$value);
} else {
$this->$name = $value;
@ -356,6 +364,70 @@ class Image
}
}
public function save_to_db()
{
global $database, $user;
$cut_name = substr($this->filename, 0, 255);
if (is_null($this->id)) {
$database->execute(
"INSERT INTO images(
owner_id, owner_ip,
filename, filesize,
hash, ext,
width, height,
posted, source
)
VALUES (
:owner_id, :owner_ip,
:filename, :filesize,
:hash, :ext,
0, 0,
now(), :source
)",
[
"owner_id" => $user->id, "owner_ip" => $_SERVER['REMOTE_ADDR'],
"filename" => $cut_name, "filesize" => $this->filesize,
"hash" => $this->hash, "ext" => strtolower($this->ext),
"source" => $this->source
]
);
$this->id = $database->get_last_insert_id('images_id_seq');
} else {
$database->execute(
"UPDATE images SET ".
"filename = :filename, filesize = :filesize, hash = :hash, ".
"ext = :ext, width = 0, height = 0, source = :source ".
"WHERE id = :id",
[
"filename" => $cut_name,
"filesize" => $this->filesize,
"hash" => $this->hash,
"ext" => strtolower($this->ext),
"source" => $this->source,
"id" => $this->id,
]
);
}
$database->execute(
"UPDATE images SET ".
"lossless = :lossless, ".
"video = :video, audio = :audio,image = :image, ".
"height = :height, width = :width, ".
"length = :length WHERE id = :id",
[
"id" => $this->id,
"width" => $this->width ?? 0,
"height" => $this->height ?? 0,
"lossless" => $database->scoresql_value_prepare($this->lossless),
"video" => $database->scoresql_value_prepare($this->video),
"image" => $database->scoresql_value_prepare($this->image),
"audio" => $database->scoresql_value_prepare($this->audio),
"length" => $this->length
]
);
}
/**
* Get this image's tags as an array.
*

View file

@ -3,17 +3,17 @@ class AdminPageTest extends ShimmiePHPUnitTestCase
{
public function testAuth()
{
send_event(new UserLoginEvent(User::by_name($this->anon_name)));
send_event(new UserLoginEvent(User::by_name(self::$anon_name)));
$page = $this->get_page('admin');
$this->assertEquals(403, $page->code);
$this->assertEquals("Permission Denied", $page->title);
send_event(new UserLoginEvent(User::by_name($this->user_name)));
send_event(new UserLoginEvent(User::by_name(self::$user_name)));
$page = $this->get_page('admin');
$this->assertEquals(403, $page->code);
$this->assertEquals("Permission Denied", $page->title);
send_event(new UserLoginEvent(User::by_name($this->admin_name)));
send_event(new UserLoginEvent(User::by_name(self::$admin_name)));
$page = $this->get_page('admin');
$this->assertEquals(200, $page->code);
$this->assertEquals("Admin Tools", $page->title);
@ -23,7 +23,7 @@ class AdminPageTest extends ShimmiePHPUnitTestCase
{
// Create a problem
$ts = time(); // we need a tag that hasn't been used before
send_event(new UserLoginEvent(User::by_name($this->admin_name)));
send_event(new UserLoginEvent(User::by_name(self::$admin_name)));
$image_id_1 = $this->post_image("tests/pbx_screenshot.jpg", "TeStCase$ts");
// Validate problem
@ -53,7 +53,7 @@ class AdminPageTest extends ShimmiePHPUnitTestCase
// Create a problem
$ts = time(); // we need a tag that hasn't been used before
send_event(new UserLoginEvent(User::by_name($this->admin_name)));
send_event(new UserLoginEvent(User::by_name(self::$admin_name)));
$database->execute(
"INSERT INTO tags(tag, count) VALUES(:tag, :count)",
["tag"=>"tes$ts", "count"=>42]
@ -74,7 +74,7 @@ class AdminPageTest extends ShimmiePHPUnitTestCase
public function testCommands()
{
send_event(new UserLoginEvent(User::by_name($this->admin_name)));
send_event(new UserLoginEvent(User::by_name(self::$admin_name)));
ob_start();
send_event(new CommandEvent(["index.php", "help"]));
send_event(new CommandEvent(["index.php", "get-page", "post/list"]));
@ -82,5 +82,8 @@ class AdminPageTest extends ShimmiePHPUnitTestCase
send_event(new CommandEvent(["index.php", "get-token"]));
send_event(new CommandEvent(["index.php", "regen-thumb", "42"]));
ob_end_clean();
// don't crash
$this->assertTrue(true);
}
}

View file

@ -48,8 +48,8 @@ class Artists extends Extension
$matches = [];
if (preg_match("/^(author|artist)[=|:](.*)$/i", $event->term, $matches)) {
$char = $matches[1];
$event->add_querylet(new Querylet("Author = :author_char", ["author_char"=>$char]));
$char = $matches[2];
$event->add_querylet(new Querylet("author = :author_char", ["author_char"=>$char]));
}
}
@ -63,7 +63,6 @@ class Artists extends Extension
}
}
public function onDatabaseUpgrade(DatabaseUpgradeEvent $event)
{
global $config, $database;

View file

@ -3,8 +3,13 @@ class ArtistsTest extends ShimmiePHPUnitTestCase
{
public function testSearch()
{
# FIXME: check that the results are there
$this->get_page("post/list/author=bob/1");
#$this->assert_response(200);
global $user;
$this->log_in_as_user();
$image_id = $this->post_image("tests/pbx_screenshot.jpg", "pbx computer screenshot");
$image = Image::by_id($image_id);
send_event(new AuthorSetEvent($image, $user, "bob"));
$this->assert_search_results(["author=bob"], [$image_id]);
}
}

View file

@ -5,7 +5,7 @@ class AutoCompleteTest extends ShimmiePHPUnitTestCase
{
public function testAuth()
{
send_event(new UserLoginEvent(User::by_name($this->anon_name)));
send_event(new UserLoginEvent(User::by_name(self::$anon_name)));
$page = $this->get_page('api/internal/autocomplete', ["s"=>"not-a-tag"]);
$this->assertEquals(200, $page->code);
$this->assertEquals(PageMode::DATA, $page->mode);

View file

@ -1,14 +1,6 @@
<?php declare(strict_types=1);
class BlotterTest extends ShimmiePHPUnitTestCase
{
public function testLogin()
{
$this->log_in_as_admin();
//$this->assert_text("Blotter Editor");
//$this->click("Blotter Editor");
//$this->log_out();
}
public function testDenial()
{
$this->get_page("blotter/editor");
@ -23,7 +15,8 @@ class BlotterTest extends ShimmiePHPUnitTestCase
{
$this->log_in_as_admin();
$this->get_page("blotter/editor");
$page = $this->get_page("blotter/editor");
$this->assertEquals(200, $page->code);
//$this->set_field("entry_text", "blotter testing");
//$this->click("Add");
//$this->assert_text("blotter testing");

View file

@ -3,7 +3,10 @@ class BrowserSearchTest extends ShimmiePHPUnitTestCase
{
public function testBasic()
{
$this->get_page("browser_search/please_dont_use_this_tag_as_it_would_break_stuff__search.xml");
$this->get_page("browser_search/test");
$page = $this->get_page("browser_search/please_dont_use_this_tag_as_it_would_break_stuff__search.xml");
$this->assertEquals(200, $page->code);
$page = $this->get_page("browser_search/test");
$this->assertEquals(200, $page->code);
}
}

View file

@ -4,7 +4,7 @@ class BulkAddTest extends ShimmiePHPUnitTestCase
{
public function testInvalidDir()
{
send_event(new UserLoginEvent(User::by_name($this->admin_name)));
send_event(new UserLoginEvent(User::by_name(self::$admin_name)));
$bae = send_event(new BulkAddEvent('asdf'));
$this->assertContains(
"Error, asdf is not a readable directory",
@ -15,7 +15,7 @@ class BulkAddTest extends ShimmiePHPUnitTestCase
public function testValidDir()
{
send_event(new UserLoginEvent(User::by_name($this->admin_name)));
send_event(new UserLoginEvent(User::by_name(self::$admin_name)));
send_event(new BulkAddEvent('tests'));
$page = $this->get_page("post/list/hash=17fc89f372ed3636e28bd25cc7f3bac1/1");
$this->assertEquals(302, $page->code);

View file

@ -15,8 +15,8 @@ class DanbooruApiTest extends ShimmiePHPUnitTestCase
$this->get_page("api/danbooru/find_tags?id=1");
$this->get_page("api/danbooru/find_tags?name=data");
$this->get_page("api/danbooru/post/show/$image_id");
//$this->assert_response(302); // FIXME
$page = $this->get_page("api/danbooru/post/show/$image_id");
$this->assertEquals(302, $page->code);
$this->get_page("post/list/md5:17fc89f372ed3636e28bd25cc7f3bac1/1");
//$this->assert_title(new PatternExpectation("/^Image \d+: data/"));

View file

@ -6,17 +6,17 @@ class FlashFileHandler extends DataHandlerExtension
{
switch ($event->ext) {
case "swf":
$event->lossless = true;
$event->video = true;
$event->image->lossless = true;
$event->image->video = true;
$info = getimagesize($event->file_name);
if (!$info) {
return null;
}
$event->image = false;
$event->image->image = false;
$event->width = $info[0];
$event->height = $info[1];
$event->image->width = $info[0];
$event->image->height = $info[1];
break;
}

View file

@ -4,15 +4,13 @@ class IcoFileHandler extends DataHandlerExtension
{
const SUPPORTED_EXTENSIONS = ["ico", "ani", "cur"];
public function onMediaCheckProperties(MediaCheckPropertiesEvent $event)
{
if (in_array($event->ext, self::SUPPORTED_EXTENSIONS)) {
$event->lossless = true;
$event->video = false;
$event->audio = false;
$event->image = ($event->ext!="ani");
$event->image->lossless = true;
$event->image->video = false;
$event->image->audio = false;
$event->image->image = ($event->ext!="ani");
$fp = fopen($event->file_name, "r");
try {
@ -24,12 +22,11 @@ class IcoFileHandler extends DataHandlerExtension
$width = $subheader['width'];
$height = $subheader['height'];
$event->width = $width == 0 ? 256 : $width;
$event->height = $height == 0 ? 256 : $height;
$event->image->width = $width == 0 ? 256 : $width;
$event->image->height = $height == 0 ? 256 : $height;
}
}
protected function supported_ext(string $ext): bool
{
return in_array(strtolower($ext), self::SUPPORTED_EXTENSIONS);

View file

@ -5,7 +5,9 @@ class IcoFileHandlerTest extends ShimmiePHPUnitTestCase
{
$this->log_in_as_user();
$image_id = $this->post_image("ext/handle_static/static/favicon.ico", "shimmie favicon");
$this->get_page("post/view/$image_id"); // test for no crash
$page = $this->get_page("post/view/$image_id");
$this->assertEquals(200, $page->code);
# FIXME: test that the thumb works
# FIXME: test that it gets displayed properly

View file

@ -6,10 +6,10 @@ class MP3FileHandler extends DataHandlerExtension
{
switch ($event->ext) {
case "mp3":
$event->audio = true;
$event->video = false;
$event->lossless = false;
$event->image = false;
$event->image->audio = true;
$event->image->video = false;
$event->image->lossless = false;
$event->image->image = false;
break;
}
// TODO: Buff out audio format support, length scanning

View file

@ -4,45 +4,42 @@ class PixelFileHandler extends DataHandlerExtension
{
const SUPPORTED_EXTENSIONS = ["jpg", "jpeg", "gif", "png", "webp"];
public function onMediaCheckProperties(MediaCheckPropertiesEvent $event)
{
if (in_array($event->ext, Media::LOSSLESS_FORMATS)) {
$event->lossless = true;
$event->image->lossless = true;
} elseif ($event->ext=="webp") {
$event->lossless = Media::is_lossless_webp($event->file_name);
$event->image->lossless = Media::is_lossless_webp($event->file_name);
}
if (in_array($event->ext, self::SUPPORTED_EXTENSIONS)) {
if ($event->lossless==null) {
$event->lossless = false;
if ($event->image->lossless==null) {
$event->image->lossless = false;
}
$event->audio = false;
$event->image->audio = false;
switch ($event->ext) {
case "gif":
$event->video = Media::is_animated_gif($event->file_name);
$event->image->video = Media::is_animated_gif($event->file_name);
break;
case "webp":
$event->video = Media::is_animated_webp($event->file_name);
$event->image->video = Media::is_animated_webp($event->file_name);
break;
default:
$event->video = false;
$event->image->video = false;
break;
}
$event->image = !$event->video;
$event->image->image = !$event->image->video;
$info = getimagesize($event->file_name);
if (!$info) {
return null;
}
$event->width = $info[0];
$event->height = $info[1];
$event->image->width = $info[0];
$event->image->height = $info[1];
}
}
protected function supported_ext(string $ext): bool
{
$ext = (($pos = strpos($ext, '?')) !== false) ? substr($ext, 0, $pos) : $ext;

View file

@ -5,6 +5,8 @@ class PixelFileHandlerTest extends ShimmiePHPUnitTestCase
{
$this->log_in_as_user();
$image_id = $this->post_image("tests/pbx_screenshot.jpg", "pbx computer screenshot");
$page = $this->get_page("post/view/$image_id");
$this->assertEquals(200, $page->code);
//$this->assert_response(302);
# FIXME: test that the thumb works

View file

@ -7,20 +7,19 @@ class SVGFileHandler extends DataHandlerExtension
{
switch ($event->ext) {
case "svg":
$event->lossless = true;
$event->video = false;
$event->audio = false;
$event->image = true;
$event->image->lossless = true;
$event->image->video = false;
$event->image->audio = false;
$event->image->image = true;
$msp = new MiniSVGParser($event->file_name);
$event->width = $msp->width;
$event->height = $msp->height;
$event->image->width = $msp->width;
$event->image->height = $msp->height;
break;
}
}
public function onDataUpload(DataUploadEvent $event)
{
if ($this->supported_ext($event->type) && $this->check_contents($event->tmpname)) {

View file

@ -31,8 +31,8 @@ class VideoFileHandler extends DataHandlerExtension
public function onMediaCheckProperties(MediaCheckPropertiesEvent $event)
{
if (in_array($event->ext, self::SUPPORTED_EXT)) {
$event->video = true;
$event->image = false;
$event->image->video = true;
$event->image->image = false;
try {
$data = Media::get_ffprobe_data($event->file_name);
@ -57,22 +57,22 @@ class VideoFileHandler extends DataHandlerExtension
}
if (array_key_exists("width", $stream) && !empty($stream["width"])
&& is_numeric($stream["width"]) && intval($stream["width"]) > ($event->width) ?? 0) {
$event->width = intval($stream["width"]);
$event->image->width = intval($stream["width"]);
}
if (array_key_exists("height", $stream) && !empty($stream["height"])
&& is_numeric($stream["height"]) && intval($stream["height"]) > ($event->height) ?? 0) {
$event->height = intval($stream["height"]);
$event->image->height = intval($stream["height"]);
}
}
}
$event->video = $video;
$event->audio = $audio;
$event->image->video = $video;
$event->image->audio = $audio;
}
}
if (array_key_exists("format", $data)&& is_array($data["format"])) {
$format = $data["format"];
if (array_key_exists("duration", $format) && is_numeric($format["duration"])) {
$event->length = floor(floatval($format["duration"]) * 1000);
$event->image->length = floor(floatval($format["duration"]) * 1000);
}
}
}

View file

@ -3,12 +3,7 @@ class HomeTest extends ShimmiePHPUnitTestCase
{
public function testHomePage()
{
$this->get_page('home');
// FIXME: this page doesn't use blocks; need assert_data_contains
//$this->assert_title('Shimmie');
//$this->assert_text('Shimmie');
# FIXME: test search box
$page = $this->get_page('home');
$this->assertStringContainsString("Posts", $page->data);
}
}

View file

@ -93,8 +93,60 @@ class ImageIO extends Extension
public function onImageAddition(ImageAdditionEvent $event)
{
global $config;
try {
$this->add_image($event);
$image = $event->image;
/*
* Validate things
*/
if (strlen(trim($image->source ?? '')) == 0) {
$image->source = null;
}
/*
* Check for an existing image
*/
$existing = Image::by_hash($image->hash);
if (!is_null($existing)) {
$handler = $config->get_string(ImageConfig::UPLOAD_COLLISION_HANDLER);
if ($handler == ImageConfig::COLLISION_MERGE || isset($_GET['update'])) {
$merged = array_merge($image->get_tag_array(), $existing->get_tag_array());
send_event(new TagSetEvent($existing, $merged));
if (isset($_GET['rating']) && isset($_GET['update']) && Extension::is_enabled(RatingsInfo::KEY)) {
send_event(new RatingSetEvent($existing, $_GET['rating']));
}
if (isset($_GET['source']) && isset($_GET['update'])) {
send_event(new SourceSetEvent($existing, $_GET['source']));
}
$event->merged = true;
$event->image = Image::by_id($existing->id);
return;
} else {
$error = "Image <a href='".make_link("post/view/{$existing->id}")."'>{$existing->id}</a> ".
"already has hash {$image->hash}:<p>".$this->theme->build_thumb_html($existing);
throw new ImageAdditionException($error);
}
}
// actually insert the info
$image->save_to_db();
log_info("image", "Uploaded Image #{$image->id} ({$image->hash})");
# at this point in time, the image's tags haven't really been set,
# and so, having $image->tag_array set to something is a lie (but
# a useful one, as we want to know what the tags are /supposed/ to
# be). Here we correct the lie, by first nullifying the wrong tags
# then using the standard mechanism to set them properly.
$tags_to_set = $image->get_tag_array();
$image->tag_array = [];
send_event(new TagSetEvent($image, $tags_to_set));
if ($image->source !== null) {
log_info("core-image", "Source for Image #{$image->id} set to: {$image->source}");
}
} catch (ImageAdditionException $e) {
throw new UploadException($e->error);
}
@ -108,7 +160,43 @@ class ImageIO extends Extension
public function onImageReplace(ImageReplaceEvent $event)
{
try {
$this->replace_image($event->id, $event->image);
$id = $event->id;
$image = $event->image;
/* Check to make sure the image exists. */
$existing = Image::by_id($id);
if (is_null($existing)) {
throw new ImageReplaceException("Image to replace does not exist!");
}
$duplicate = Image::by_hash($image->hash);
if (!is_null($duplicate) && $duplicate->id!=$id) {
$error = "Image <a href='" . make_link("post/view/{$duplicate->id}") . "'>{$duplicate->id}</a> " .
"already has hash {$image->hash}:<p>" . $this->theme->build_thumb_html($duplicate);
throw new ImageReplaceException($error);
}
if (strlen(trim($image->source)) == 0) {
$image->source = $existing->get_source();
}
// Update the data in the database.
$image->save_to_db();
/*
This step could be optional, ie: perhaps move the image somewhere
and have it stored in a 'replaced images' list that could be
inspected later by an admin?
*/
log_debug("image", "Removing image with hash " . $existing->hash);
$existing->remove_image_only(); // Actually delete the old image file from disk
/* Generate new thumbnail */
send_event(new ThumbnailGenerationEvent($image->hash, strtolower($image->ext)));
log_info("image", "Replaced Image #{$id} with ({$image->hash})");
} catch (ImageReplaceException $e) {
throw new UploadException($e->error);
}
@ -159,83 +247,6 @@ class ImageIO extends Extension
$event->panel->add_block($sb);
}
private function add_image(ImageAdditionEvent $event)
{
global $user, $database, $config;
$image = $event->image;
/*
* Validate things
*/
if (strlen(trim($image->source ?? '')) == 0) {
$image->source = null;
}
/*
* Check for an existing image
*/
$existing = Image::by_hash($image->hash);
if (!is_null($existing)) {
$handler = $config->get_string(ImageConfig::UPLOAD_COLLISION_HANDLER);
if ($handler == ImageConfig::COLLISION_MERGE || isset($_GET['update'])) {
$merged = array_merge($image->get_tag_array(), $existing->get_tag_array());
send_event(new TagSetEvent($existing, $merged));
if (isset($_GET['rating']) && isset($_GET['update']) && Extension::is_enabled(RatingsInfo::KEY)) {
send_event(new RatingSetEvent($existing, $_GET['rating']));
}
if (isset($_GET['source']) && isset($_GET['update'])) {
send_event(new SourceSetEvent($existing, $_GET['source']));
}
$event->merged = true;
$event->image = Image::by_id($existing->id);
return;
} else {
$error = "Image <a href='".make_link("post/view/{$existing->id}")."'>{$existing->id}</a> ".
"already has hash {$image->hash}:<p>".$this->theme->build_thumb_html($existing);
throw new ImageAdditionException($error);
}
}
// actually insert the info
$database->Execute(
"INSERT INTO images(
owner_id, owner_ip, filename, filesize,
hash, ext, width, height, posted, source
)
VALUES (
:owner_id, :owner_ip, :filename, :filesize,
:hash, :ext, 0, 0, now(), :source
)",
[
"owner_id" => $user->id, "owner_ip" => $_SERVER['REMOTE_ADDR'], "filename" => substr($image->filename, 0, 255), "filesize" => $image->filesize,
"hash" => $image->hash, "ext" => strtolower($image->ext), "source" => $image->source
]
);
$image->id = $database->get_last_insert_id('images_id_seq');
log_info("image", "Uploaded Image #{$image->id} ({$image->hash})");
# at this point in time, the image's tags haven't really been set,
# and so, having $image->tag_array set to something is a lie (but
# a useful one, as we want to know what the tags are /supposed/ to
# be). Here we correct the lie, by first nullifying the wrong tags
# then using the standard mechanism to set them properly.
$tags_to_set = $image->get_tag_array();
$image->tag_array = [];
send_event(new TagSetEvent($image, $tags_to_set));
if ($image->source !== null) {
log_info("core-image", "Source for Image #{$image->id} set to: {$image->source}");
}
try {
Media::update_image_media_properties($image->hash, strtolower($image->ext));
} catch (MediaException $e) {
log_warning("add_image", "Error while running update_image_media_properties: ".$e->getMessage());
}
}
private function send_file(int $image_id, string $type)
{
global $config;
@ -294,66 +305,4 @@ class ImageIO extends Extension
));
}
}
private function replace_image(int $id, Image $image)
{
global $database;
/* Check to make sure the image exists. */
$existing = Image::by_id($id);
if (is_null($existing)) {
throw new ImageReplaceException("Image to replace does not exist!");
}
$duplicate = Image::by_hash($image->hash);
if (!is_null($duplicate) && $duplicate->id!=$id) {
$error = "Image <a href='" . make_link("post/view/{$duplicate->id}") . "'>{$duplicate->id}</a> " .
"already has hash {$image->hash}:<p>" . $this->theme->build_thumb_html($duplicate);
throw new ImageReplaceException($error);
}
if (strlen(trim($image->source)) == 0) {
$image->source = $existing->get_source();
}
// Update the data in the database.
$database->Execute(
"UPDATE images SET
filename = :filename, filesize = :filesize, hash = :hash,
ext = :ext, width = 0, height = 0, source = :source
WHERE
id = :id
",
[
"filename" => substr($image->filename, 0, 255),
"filesize" => $image->filesize,
"hash" => $image->hash,
"ext" => strtolower($image->ext),
"source" => $image->source,
"id" => $id,
]
);
/*
This step could be optional, ie: perhaps move the image somewhere
and have it stored in a 'replaced images' list that could be
inspected later by an admin?
*/
log_debug("image", "Removing image with hash " . $existing->hash);
$existing->remove_image_only(); // Actually delete the old image file from disk
try {
Media::update_image_media_properties($image->hash, $image->ext);
} catch (MediaException $e) {
log_warning("image_replace", "Error while running update_image_media_properties: ".$e->getMessage());
}
/* Generate new thumbnail */
send_event(new ThumbnailGenerationEvent($image->hash, strtolower($image->ext)));
log_info("image", "Replaced Image #{$id} with ({$image->hash})");
}
}

View file

@ -14,7 +14,10 @@ class ImageIOTest extends ShimmiePHPUnitTestCase
//$this->assert_title("Image $image_id: test");
# test that serving manually doesn't cause errors
$this->get_page("image/$image_id/moo.jpg");
$this->get_page("thumb/$image_id/moo.jpg");
$page = $this->get_page("image/$image_id/moo.jpg");
$this->assertEquals(200, $page->code);
$page = $this->get_page("thumb/$image_id/moo.jpg");
$this->assertEquals(200, $page->code);
}
}

View file

@ -1,20 +1,6 @@
<?php declare(strict_types=1);
class IndexTest extends ShimmiePHPUnitTestCase
{
private function upload()
{
$this->log_in_as_user();
$image_id_1 = $this->post_image("tests/pbx_screenshot.jpg", "thing computer screenshot pbx phone");
$image_id_2 = $this->post_image("tests/bedroom_workshop.jpg", "thing computer computing bedroom workshop");
$this->log_out();
# make sure both uploads were ok
$this->assertTrue($image_id_1 > 0);
$this->assertTrue($image_id_2 > 0);
return [$image_id_1, $image_id_2];
}
public function testIndexPage()
{
$this->get_page('post/list');
@ -23,6 +9,7 @@ class IndexTest extends ShimmiePHPUnitTestCase
$this->log_in_as_user();
$this->post_image("tests/pbx_screenshot.jpg", "pbx computer screenshot");
$this->post_image("tests/bedroom_workshop.jpg", "thing computer computing bedroom workshop");
$this->log_out();
$this->get_page('post/list');
@ -41,173 +28,153 @@ class IndexTest extends ShimmiePHPUnitTestCase
$this->get_page('post/list/99999');
$this->assert_response(404);
# No results: 404
$this->get_page('post/list/maumaumau/1');
$this->assert_response(404);
# One result: 302
$this->get_page("post/list/pbx/1");
$this->assert_response(302);
# Multiple results: 200
$this->get_page('post/list/computer/1');
$this->assert_response(200);
}
// base case
public function testUpload()
{
$this->log_in_as_user();
$image_id_1 = $this->post_image("tests/pbx_screenshot.jpg", "thing computer screenshot pbx phone");
$image_id_2 = $this->post_image("tests/bedroom_workshop.jpg", "thing computer computing bedroom workshop");
$this->log_out();
# make sure both uploads were ok
$this->assertTrue($image_id_1 > 0);
$this->assertTrue($image_id_2 > 0);
return [$image_id_1, $image_id_2];
}
/* * * * * * * * * * *
* Tag Search *
* * * * * * * * * * */
public function testTagSearchNoResults()
/** @depends testUpload */
public function testTagSearchNoResults($image_ids)
{
$image_ids = $this->upload();
$this->get_page('post/list/maumaumau/1');
$this->assert_response(404);
$this->assert_search_results(["maumaumau"], []);
}
public function testTagSearchOneResult()
/** @depends testUpload */
public function testTagSearchOneResult($image_ids)
{
$image_ids = $this->upload();
$this->get_page("post/list/pbx/1");
$this->assert_response(302);
$this->assert_search_results(["pbx"], [$image_ids[0]]);
}
public function testTagSearchManyResults()
/** @depends testUpload */
public function testTagSearchManyResults($image_ids)
{
$image_ids = $this->upload();
$this->get_page('post/list/computer/1');
$this->assert_response(200);
$this->assert_title("computer");
$this->assert_search_results(["computer"], [$image_ids[1], $image_ids[0]]);
}
/* * * * * * * * * * *
* Multi-Tag Search *
* * * * * * * * * * */
public function testMultiTagSearchNoResults()
/** @depends testUpload */
public function testMultiTagSearchNoResults($image_ids)
{
$image_ids = $this->upload();
# multiple tags, one of which doesn't exist
# (test the "one tag doesn't exist = no hits" path)
$this->get_page('post/list/computer asdfasdfwaffle/1');
$this->assert_response(404);
$this->assert_search_results(["computer", "asdfasdfwaffle"], []);
}
public function testMultiTagSearchOneResult()
/** @depends testUpload */
public function testMultiTagSearchOneResult($image_ids)
{
$image_ids = $this->upload();
$this->get_page('post/list/computer screenshot/1');
$this->assert_response(302);
$this->assert_search_results(["computer", "screenshot"], [$image_ids[0]]);
}
public function testMultiTagSearchManyResults()
/** @depends testUpload */
public function testMultiTagSearchManyResults($image_ids)
{
$image_ids = $this->upload();
$this->get_page('post/list/computer thing/1');
$this->assert_response(200);
$this->assert_search_results(["computer", "thing"], [$image_ids[1], $image_ids[0]]);
}
/* * * * * * * * * * *
* Meta Search *
* * * * * * * * * * */
public function testMetaSearchNoResults()
/** @depends testUpload */
public function testMetaSearchNoResults($image_ids)
{
$this->get_page('post/list/hash=1234567890/1');
$this->assert_response(404);
$this->assert_search_results(["hash=1234567890"], []);
}
public function testMetaSearchOneResult()
/** @depends testUpload */
public function testMetaSearchOneResult($image_ids)
{
$image_ids = $this->upload();
$this->get_page("post/list/hash=feb01bab5698a11dd87416724c7a89e3/1");
$this->assert_response(302);
$this->get_page("post/list/md5=feb01bab5698a11dd87416724c7a89e3/1");
$this->assert_response(302);
$this->get_page("post/list/id={$image_ids[1]}/1");
$this->assert_response(302);
$this->get_page("post/list/filename=screenshot/1");
$this->assert_response(302);
$this->assert_search_results(["hash=feb01bab5698a11dd87416724c7a89e3"], [$image_ids[0]]);
$this->assert_search_results(["md5=feb01bab5698a11dd87416724c7a89e3"], [$image_ids[0]]);
$this->assert_search_results(["id={$image_ids[1]}"], [$image_ids[1]]);
$this->assert_search_results(["filename=screenshot"], [$image_ids[0]]);
}
public function testMetaSearchManyResults()
/** @depends testUpload */
public function testMetaSearchManyResults($image_ids)
{
$image_ids = $this->upload();
$this->get_page('post/list/size=640x480/1');
$this->assert_response(200);
$this->get_page("post/list/tags=5/1");
$this->assert_response(200);
$this->get_page("post/list/ext=jpg/1");
$this->assert_response(200);
$this->assert_search_results(["size=640x480"], [$image_ids[1], $image_ids[0]]);
$this->assert_search_results(["tags=5"], [$image_ids[1], $image_ids[0]]);
$this->assert_search_results(["ext=jpg"], [$image_ids[1], $image_ids[0]]);
}
/* * * * * * * * * * *
* Wildcards *
* * * * * * * * * * */
public function testWildSearchNoResults()
/** @depends testUpload */
public function testWildSearchNoResults($image_ids)
{
$image_ids = $this->upload();
$this->get_page("post/list/asdfasdf*/1");
$this->assert_response(404);
$this->assert_search_results(["asdfasdf*"], []);
}
public function testWildSearchOneResult()
/** @depends testUpload */
public function testWildSearchOneResult($image_ids)
{
$image_ids = $this->upload();
// Only the first image matches both the wildcard and the tag.
// This checks for https://github.com/shish/shimmie2/issues/547
// (comp* is expanded to "computer computing", then we searched
// for images which match two or more of the tags in
// "computer computing screenshot")
$this->get_page("post/list/comp* screenshot/1");
$this->assert_response(302);
$this->assert_search_results(["comp*", "screenshot"], [$image_ids[0]]);
}
public function testWildSearchManyResults()
/** @depends testUpload */
public function testWildSearchManyResults($image_ids)
{
$image_ids = $this->upload();
// two images match comp* - one matches it once,
// one matches it twice
$this->get_page("post/list/comp*/1");
$this->assert_response(200);
$this->assert_search_results(["comp*"], [$image_ids[1], $image_ids[0]]);
}
/* * * * * * * * * * *
* Mixed *
* * * * * * * * * * */
public function testMixedSearchTagMeta()
/** @depends testUpload */
public function testMixedSearchTagMeta($image_ids)
{
$image_ids = $this->upload();
# multiple tags, many results
$this->get_page('post/list/computer size=640x480/1');
$this->assert_response(200);
global $database;
// multiple tags, many results
$this->assert_search_results(["computer", "size=640x480"], [$image_ids[1], $image_ids[0]]);
}
// tag + negative
// wildcards + ???
/* * * * * * * * * * *
* Other *
* - negative tags *
* - wildcards *
* Negative *
* * * * * * * * * * */
public function testOther()
/** @depends testUpload */
public function testNegative($image_ids)
{
$image_ids = $this->upload();
// negative tag, should have one result
$this->assert_search_results(["computer", "-pbx"], [$image_ids[1]]);
# negative tag, should have one result
$this->get_page('post/list/computer -pbx/1');
$this->assert_response(302);
# negative tag alone, should work
# FIXME: known broken in mysql
$this->get_page('post/list/-pbx/1');
$this->assert_response(302);
# test various search methods
$this->get_page("post/list/bedroo*/1");
$this->assert_response(302);
// negative tag alone, should work
$this->assert_search_results(["-pbx"], [$image_ids[1]]);
}
}

View file

@ -50,7 +50,9 @@ class IPBanTest extends ShimmiePHPUnitTestCase
public function test_all()
{
// just test it doesn't crash for now
$this->log_in_as_admin();
$this->get_page('ip_ban/list?r_all=on'); // just test it doesn't crash for now
$page = $this->get_page('ip_ban/list', ['r_all'=>'on']);
$this->assertEquals(200, $page->code);
}
}

View file

@ -5,9 +5,11 @@ class LogDatabaseTest extends ShimmiePHPUnitTestCase
{
$this->log_in_as_admin();
$this->get_page("log/view");
$this->get_page("log/view?module=core-image");
$this->get_page("log/view?time=2012-03-01");
$this->get_page("log/view?user=demo");
$this->get_page("log/view?priority=10");
$this->get_page("log/view", ["r_module"=>"core-image"]);
$this->get_page("log/view", ["r_time"=>"2012-03-01"]);
$this->get_page("log/view", ["r_user"=>"demo"]);
$page = $this->get_page("log/view", ["r_priority"=>"10"]);
$this->assertEquals(200, $page->code);
}
}

View file

@ -45,20 +45,15 @@ class MediaResizeEvent extends Event
class MediaCheckPropertiesEvent extends Event
{
public $image;
public $file_name;
public $ext;
public $lossless = null;
public $audio = null;
public $video = null;
public $image = null;
public $length = null;
public $height = null;
public $width = null;
public function __construct(string $file_name, string $ext)
public function __construct(Image $image)
{
parent::__construct();
$this->file_name = $file_name;
$this->ext = $ext;
$this->image = $image;
$this->file_name = warehouse_path(Image::IMAGE_DIR, $image->hash);
$this->ext = strtolower($image->ext);
}
}

View file

@ -85,7 +85,8 @@ class Media extends Extension
if ($event->page_matches("media_rescan/") && $user->can(Permissions::RESCAN_MEDIA) && isset($_POST['image_id'])) {
$image = Image::by_id(int_escape($_POST['image_id']));
$this->update_image_media_properties($image->hash, $image->ext);
send_event(new MediaCheckPropertiesEvent($image));
$image->save_to_db();
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/view/$image->id"));
@ -163,7 +164,8 @@ class Media extends Extension
$failed = 0;
foreach ($event->items as $image) {
try {
$this->update_image_media_properties($image->hash, $image->ext);
send_event(new MediaCheckPropertiesEvent($image));
$image->save_media_properties();
$total++;
} catch (MediaException $e) {
$failed++;
@ -185,7 +187,8 @@ class Media extends Extension
$uid = $event->args[0];
$image = Image::by_id_or_hash($uid);
if ($image) {
$this->update_image_media_properties($image->hash, $image->ext);
send_event(new MediaCheckPropertiesEvent($image));
$image->save_to_db();
} else {
print("No post with ID '$uid'\n");
}
@ -282,69 +285,13 @@ class Media extends Extension
}
}
public function onTagTermParse(TagTermParseEvent $event)
public function onTagTermCheck(TagTermCheckEvent $event)
{
$matches = [];
if (preg_match(self::CONTENT_SEARCH_TERM_REGEX, strtolower($event->term), $matches) && $event->parse) {
if (preg_match(self::CONTENT_SEARCH_TERM_REGEX, $event->term)) {
$event->metatag = true;
}
}
private function media_rescan(): bool
{
$ext = "";
if (array_key_exists("media_rescan_type", $_POST)) {
$ext = $_POST["media_rescan_type"];
}
$results = $this->get_images($ext);
foreach ($results as $result) {
$this->update_image_media_properties($result["hash"], $result["ext"]);
}
return true;
}
public static function update_image_media_properties(string $hash, string $ext)
{
global $database;
$path = warehouse_path(Image::IMAGE_DIR, $hash);
$mcpe = new MediaCheckPropertiesEvent($path, $ext);
send_event($mcpe);
$database->execute(
"UPDATE images SET
lossless = :lossless, video = :video, audio = :audio,image = :image,
height = :height, width = :width,
length = :length WHERE hash = :hash",
[
"hash" => $hash,
"width" => $mcpe->width ?? 0,
"height" => $mcpe->height ?? 0,
"lossless" => $database->scoresql_value_prepare($mcpe->lossless),
"video" => $database->scoresql_value_prepare($mcpe->video),
"image" => $database->scoresql_value_prepare($mcpe->image),
"audio" => $database->scoresql_value_prepare($mcpe->audio),
"length" => $mcpe->length
]
);
}
public function get_images(String $ext = null)
{
global $database;
$query = "SELECT id, hash, ext FROM images ";
$args = [];
if (!empty($ext)) {
$query .= " WHERE ext = :ext";
$args["ext"] = $ext;
}
return $database->get_all($query, $args);
}
/**
* Check Memory usage limits
*

View file

@ -274,21 +274,24 @@ class NumericScore extends Extension
}
}
public function onTagTermCheck(TagTermCheckEvent $event)
{
if (preg_match("/^vote[=|:](up|down|remove)$/i", $event->term)) {
$event->metatag = true;
}
}
public function onTagTermParse(TagTermParseEvent $event)
{
$matches = [];
if (preg_match("/^vote[=|:](up|down|remove)$/", $event->term, $matches) && $event->parse) {
if (preg_match("/^vote[=|:](up|down|remove)$/", $event->term, $matches)) {
global $user;
$score = ($matches[1] == "up" ? 1 : ($matches[1] == "down" ? -1 : 0));
if (!$user->is_anonymous()) {
send_event(new NumericScoreSetEvent($event->id, $user, $score));
send_event(new NumericScoreSetEvent($event->image_id, $user, $score));
}
}
if (!empty($matches)) {
$event->metatag = true;
}
}
public function onPageSubNavBuilding(PageSubNavBuildingEvent $event)

View file

@ -4,6 +4,7 @@ class OekakiTest extends ShimmiePHPUnitTestCase
public function testLog()
{
$this->log_in_as_user();
$this->get_page("oekaki/create");
$page = $this->get_page("oekaki/create");
$this->assertEquals(200, $page->code);
}
}

View file

@ -6,14 +6,14 @@ class PrivMsgTest extends ShimmiePHPUnitTestCase
// Send from admin to user
$this->log_in_as_admin();
send_event(new SendPMEvent(new PM(
User::by_name($this->admin_name)->id,
User::by_name(self::$admin_name)->id,
"0.0.0.0",
User::by_name($this->user_name)->id,
User::by_name(self::$user_name)->id,
"message demo to test"
)));
// Check that admin can see user's messages
$this->get_page("user/{$this->user_name}");
$this->get_page("user/" . self::$user_name);
$this->assert_text("message demo to test");
// Check that user can see own messages

View file

@ -404,10 +404,16 @@ class Pools extends Extension
}
}
public function onTagTermCheck(TagTermCheckEvent $event)
{
if (preg_match("/^pool[=|:]([^:]*|lastcreated):?([0-9]*)$/i", $event->term)) {
$event->metatag = true;
}
}
public function onTagTermParse(TagTermParseEvent $event)
{
$matches = [];
if (preg_match("/^pool[=|:]([^:]*|lastcreated):?([0-9]*)$/i", $event->term, $matches)) {
global $user;
$poolTag = (string)str_replace("_", " ", $matches[1]);
@ -421,16 +427,11 @@ class Pools extends Extension
$pool = $this->get_single_pool_from_title($poolTag);
}
if ($pool ? $this->have_permission($user, $pool) : false) {
$image_order = ($matches[2] ?: 0);
$this->add_post($pool['id'], $event->id, true, $image_order);
$this->add_post($pool['id'], $event->image_id, true, $image_order);
}
}
if (!empty($matches)) {
$event->metatag = true;
}
}
public function onBulkActionBlockBuilding(BulkActionBlockBuildingEvent $event)

View file

@ -253,12 +253,19 @@ class Ratings extends Extension
}
}
public function onTagTermCheck(TagTermCheckEvent $event)
{
if (preg_match($this->search_regexp, $event->term)) {
$event->metatag = true;
}
}
public function onTagTermParse(TagTermParseEvent $event)
{
global $user;
$matches = [];
if (preg_match($this->search_regexp, strtolower($event->term), $matches) && $event->parse) {
if (preg_match($this->search_regexp, strtolower($event->term), $matches)) {
$ratings = $matches[1] ? $matches[1] : $matches[2][0];
if (count($matches)>2&&in_array($matches[2], self::UNRATED_KEYWORDS)) {
@ -267,14 +274,10 @@ class Ratings extends Extension
$ratings = array_intersect(str_split($ratings), Ratings::get_user_class_privs($user));
$rating = $ratings[0];
$image = Image::by_id($event->id);
$image = Image::by_id($event->image_id);
$re = new RatingSetEvent($image, $rating);
send_event($re);
}
if (!empty($matches)) {
$event->metatag = true;
}
}
public function onAdminBuilding(AdminBuildingEvent $event)

View file

@ -9,22 +9,15 @@ class RatingsTest extends ShimmiePHPUnitTestCase
send_event(new RatingSetEvent($image, "s"));
# search for it in various ways
$page = $this->get_page("post/list/rating=Safe/1");
$this->assertEquals("/post/view/1", $page->redirect);
$page = $this->get_page("post/list/rating=s/1");
$this->assertEquals("/post/view/1", $page->redirect);
$page = $this->get_page("post/list/rating=sqe/1");
$this->assertEquals("/post/view/1", $page->redirect);
$this->assert_search_results(["rating=Safe"], [$image_id]);
$this->assert_search_results(["rating=s"], [$image_id]);
$this->assert_search_results(["rating=sqe"], [$image_id]);
# test that search by tag still works
$page = $this->get_page("post/list/pbx/1");
$this->assertEquals("/post/view/1", $page->redirect);
$this->assert_search_results(["pbx"], [$image_id]);
# searching for a different rating should return nothing
$page = $this->get_page("post/list/rating=q/1");
$this->assertEquals("No Images Found", $page->heading);
$this->assert_search_results(["rating=q"], []);
}
public function testRatingExplicit()
@ -38,7 +31,6 @@ class RatingsTest extends ShimmiePHPUnitTestCase
# the explicit image shouldn't show up in anon's searches
$this->log_out();
$page = $this->get_page("post/list/pbx/1");
$this->assertEquals("No Images Found", $page->heading);
$this->assert_search_results(["pbx"], []);
}
}

View file

@ -9,5 +9,5 @@ class RelationshipsInfo extends ExtensionInfo
public $authors = ["Angus Johnston"=>"admin@codeanimu.net"];
public $license = self::LICENSE_GPLV2;
public $description = "Allow posts to have relationships (parent/child).";
public $db_support = [DatabaseDriver::MYSQL, DatabaseDriver::PGSQL];
//public $db_support = [DatabaseDriver::MYSQL, DatabaseDriver::PGSQL];
}

View file

@ -5,7 +5,6 @@ class ImageRelationshipSetEvent extends Event
public $child_id;
public $parent_id;
public function __construct(int $child_id, int $parent_id)
{
parent::__construct();
@ -19,6 +18,12 @@ class Relationships extends Extension
{
public const NAME = "Relationships";
public function onInitExt(InitExtEvent $event)
{
Image::$bool_props[] = "has_children";
Image::$int_props[] = "parent_id";
}
public function onDatabaseUpgrade(DatabaseUpgradeEvent $event)
{
global $database;
@ -86,27 +91,27 @@ class Relationships extends Extension
}
}
public function onTagTermCheck(TagTermCheckEvent $event)
{
if (preg_match("/^(parent|child)[=|:](.*)$/i", $event->term)) {
$event->metatag = true;
}
}
public function onTagTermParse(TagTermParseEvent $event)
{
$matches = [];
if (preg_match("/^parent[=|:]([0-9]+|none)$/", $event->term, $matches) && $event->parse) {
if (preg_match("/^parent[=|:]([0-9]+|none)$/", $event->term, $matches)) {
$parentID = $matches[1];
if ($parentID == "none" || $parentID == "0") {
$this->remove_parent($event->id);
$this->remove_parent($event->image_id);
} else {
send_event(new ImageRelationshipSetEvent($event->id, $parentID));
send_event(new ImageRelationshipSetEvent($event->image_id, (int)$parentID));
}
} elseif (preg_match("/^child[=|:]([0-9]+)$/", $event->term, $matches) && $event->parse) {
} elseif (preg_match("/^child[=|:]([0-9]+)$/", $event->term, $matches)) {
$childID = $matches[1];
send_event(new ImageRelationshipSetEvent($childID, $event->id));
}
if (!empty($matches)) {
$event->metatag = true;
send_event(new ImageRelationshipSetEvent((int)$childID, $event->image_id));
}
}
@ -133,23 +138,25 @@ class Relationships extends Extension
global $database;
$old_parent = $database->get_one("SELECT parent_id FROM images WHERE id = :cid", ["cid"=>$event->child_id]);
if (!is_null($old_parent)) {
$old_parent = (int)$old_parent;
}
if ($old_parent!=$event->parent_id) {
if ($database->get_row("SELECT 1 FROM images WHERE id = :pid", ["pid" => $event->parent_id])) {
$result = $database->execute("UPDATE images SET parent_id = :pid WHERE id = :cid", ["pid" => $event->parent_id, "cid" => $event->child_id]);
if ($old_parent == $event->parent_id) {
return; // no change
}
if (!Image::by_id($event->parent_id) || !Image::by_id($event->child_id)) {
return; // one of the images doesn't exist
}
if ($result->rowCount() > 0) {
$database->execute("UPDATE images SET has_children = TRUE WHERE id = :pid", ["pid" => $event->parent_id]);
$database->execute("UPDATE images SET parent_id = :pid WHERE id = :cid", ["pid" => $event->parent_id, "cid" => $event->child_id]);
$database->execute("UPDATE images SET has_children = TRUE WHERE id = :pid", ["pid" => $event->parent_id]);
if ($old_parent!=null) {
$this->set_has_children($old_parent);
}
}
}
if ($old_parent!=null) {
$this->set_has_children($old_parent);
}
}
public static function get_children(Image $image, int $omit = null): array
{
global $database;
@ -171,7 +178,7 @@ class Relationships extends Extension
if ($parentID) {
$database->execute("UPDATE images SET parent_id = NULL WHERE id = :iid", ["iid"=>$imageID]);
$this->set_has_children($parentID);
$this->set_has_children((int)$parentID);
}
}
@ -180,11 +187,17 @@ class Relationships extends Extension
global $database;
// Doesn't work on pgsql
// $database->execute("UPDATE images SET has_children = (SELECT * FROM (SELECT CASE WHEN COUNT(*) > 0 THEN 1 ELSE 0 END FROM images WHERE parent_id = :pid) AS sub)
// WHERE id = :pid", ["pid"=>$parentID]);
// $database->execute("
// UPDATE images
// SET has_children = (SELECT * FROM (SELECT CASE WHEN COUNT(*) > 0 THEN 1 ELSE 0 END FROM images WHERE parent_id = :pid) AS sub)
// WHERE id = :pid
// ", ["pid"=>$parentID]);
$database->execute(
"UPDATE images SET has_children = EXISTS (SELECT 1 FROM images WHERE parent_id = :pid) WHERE id = :pid",
"UPDATE images
SET has_children = EXISTS (
SELECT 1 FROM images WHERE parent_id = :pid
) WHERE id = :pid",
["pid"=>$parent_id]
);
}

View file

@ -1,7 +1,11 @@
<?php declare(strict_types=1);
class RelationshipsTest extends ShimmiePHPUnitTestCase
{
public function testSetParent()
//=================================================================
// Set by box
//=================================================================
public function testNoParent()
{
$this->log_in_as_user();
@ -20,81 +24,85 @@ class RelationshipsTest extends ShimmiePHPUnitTestCase
$this->assertFalse($image_2->has_children);
$this->assertFalse($image_3->has_children);
$this->get_page("post/view/$image_id_2");
$this->assert_title("Image $image_id_2: pbx");
$this->markTestIncomplete();
$this->set_field("tag_edit__parent", $image_id_1);
$this->click("Set");
$image_1 = Image::by_id($image_id_1);
$image_2 = Image::by_id($image_id_2);
$image_3 = Image::by_id($image_id_3);
$this->assertNull($image_1->parent_id);
$this->assertEquals($image_id_1, $image_2->parent_id);
$this->assertNull($image_3->parent_id);
$this->assertTrue($image_1->has_children);
$this->assertFalse($image_2->has_children);
$this->assertFalse($image_3->has_children);
// Test changing to a different parent
$this->get_page("post/view/$image_id_2");
$this->assert_title("Image $image_id_2: pbx");
$this->markTestIncomplete();
$this->set_field("tag_edit__parent", $image_id_3);
$this->click("Set");
$image_1 = Image::by_id($image_id_1);
$image_2 = Image::by_id($image_id_2);
$image_3 = Image::by_id($image_id_3);
$this->assertNull($image_1->parent_id);
$this->assertEquals($image_id_3, $image_2->parent_id);
$this->assertNull($image_3->parent_id);
$this->assertFalse($image_2->has_children);
$this->assertFalse($image_2->has_children);
$this->assertTrue($image_3->has_children);
// Test setting parent to none
$this->get_page("post/view/$image_id_2");
$this->assert_title("Image $image_id_2: pbx");
$this->markTestIncomplete();
$this->set_field("tag_edit__parent", "");
$this->click("Set");
$image_1 = Image::by_id($image_id_1);
$image_2 = Image::by_id($image_id_2);
$image_3 = Image::by_id($image_id_3);
$this->assertNull($image_1->parent_id);
$this->assertNull($image_2->parent_id);
$this->assertNull($image_3->parent_id);
$this->assertFalse($image_2->has_children);
$this->assertFalse($image_2->has_children);
$this->assertFalse($image_3->has_children);
$this->log_out();
$this->log_in_as_admin();
$this->delete_image($image_id_1);
$this->delete_image($image_id_2);
$this->delete_image($image_id_3);
$this->log_out();
return [$image_1, $image_2, $image_3];
}
public function testSetParentByTag()
/**
* @depends testNoParent
*/
public function testSetParent($imgs)
{
[$image_1, $image_2, $image_3] = $imgs;
send_event(new ImageRelationshipSetEvent($image_2->id, $image_1->id));
// refresh data from database
$image_1 = Image::by_id($image_1->id);
$image_2 = Image::by_id($image_2->id);
$image_3 = Image::by_id($image_3->id);
$this->assertNull($image_1->parent_id);
$this->assertEquals($image_1->id, $image_2->parent_id);
$this->assertNull($image_3->parent_id);
$this->assertTrue($image_1->has_children);
$this->assertFalse($image_2->has_children);
$this->assertFalse($image_3->has_children);
return [$image_1, $image_2, $image_3];
}
/**
* @depends testSetParent
*/
public function testChangeParent($imgs)
{
[$image_1, $image_2, $image_3] = $imgs;
send_event(new ImageRelationshipSetEvent($image_2->id, $image_3->id));
// refresh data from database
$image_1 = Image::by_id($image_1->id);
$image_2 = Image::by_id($image_2->id);
$image_3 = Image::by_id($image_3->id);
$this->assertNull($image_1->parent_id);
$this->assertEquals($image_3->id, $image_2->parent_id);
$this->assertNull($image_3->parent_id);
$this->assertFalse($image_2->has_children);
$this->assertFalse($image_2->has_children);
$this->assertTrue($image_3->has_children);
return [$image_1, $image_2, $image_3];
}
/**
* @depends testChangeParent
*/
public function testRemoveParent($imgs)
{
[$image_1, $image_2, $image_3] = $imgs;
global $database;
$database->execute("UPDATE images SET parent_id=NULL, has_children=FALSE");
// FIXME: send_event(new ImageRelationshipSetEvent($image_2->id, null));
// refresh data from database
$image_1 = Image::by_id($image_1->id);
$image_2 = Image::by_id($image_2->id);
$image_3 = Image::by_id($image_3->id);
$this->assertNull($image_1->parent_id);
$this->assertNull($image_2->parent_id);
$this->assertNull($image_3->parent_id);
$this->assertFalse($image_2->has_children);
$this->assertFalse($image_2->has_children);
$this->assertFalse($image_3->has_children);
}
//=================================================================
// Set by tag
//=================================================================
public function testSetParentByTagBase()
{
$this->log_in_as_user();
$image_id_1 = $this->post_image("tests/pbx_screenshot.jpg", "pbx");
@ -112,81 +120,77 @@ class RelationshipsTest extends ShimmiePHPUnitTestCase
$this->assertFalse($image_2->has_children);
$this->assertFalse($image_3->has_children);
// Test settings parent:#
return [$image_1, $image_2, $image_3];
}
$this->get_page("post/view/$image_id_2");
$this->assert_title("Image $image_id_2: pbx");
/**
* @depends testSetParentByTagBase
*/
public function testSetParentByTag($imgs)
{
[$image_1, $image_2, $image_3] = $imgs;
$this->markTestIncomplete();
send_event(new TagSetEvent($image_2, ["pbx", "parent:{$image_1->id}"]));
$this->set_field("tag_edit__tags", "pbx parent:$image_id_1");
$this->click("Set");
$this->assert_title("Image $image_id_2: pbx");
$image_1 = Image::by_id($image_id_1);
$image_2 = Image::by_id($image_id_2);
$image_3 = Image::by_id($image_id_3);
// refresh data from database
$image_1 = Image::by_id($image_1->id);
$image_2 = Image::by_id($image_2->id);
$image_3 = Image::by_id($image_3->id);
$this->assertEquals(["pbx"], $image_2->get_tag_array());
$this->assertNull($image_1->parent_id);
$this->assertEquals($image_id_1, $image_2->parent_id);
$this->assertEquals($image_1->id, $image_2->parent_id);
$this->assertNull($image_3->parent_id);
$this->assertTrue($image_1->has_children);
$this->assertFalse($image_2->has_children);
$this->assertFalse($image_3->has_children);
// Test settings child:#
return [$image_1, $image_2, $image_3];
}
$this->get_page("post/view/$image_id_3");
$this->assert_title("Image $image_id_3: pbx");
/**
* @depends testSetParentByTag
*/
public function testSetChildByTag($imgs)
{
[$image_1, $image_2, $image_3] = $imgs;
$this->markTestIncomplete();
send_event(new TagSetEvent($image_3, ["pbx", "child:{$image_1->id}"]));
$this->set_field("tag_edit__tags", "pbx child:$image_id_1");
$this->click("Set");
// refresh data from database
$image_1 = Image::by_id($image_1->id);
$image_2 = Image::by_id($image_2->id);
$image_3 = Image::by_id($image_3->id);
$this->assert_title("Image $image_id_3: pbx");
$image_1 = Image::by_id($image_id_1);
$image_2 = Image::by_id($image_id_2);
$image_3 = Image::by_id($image_id_3);
$this->assertEquals($image_id_3, $image_1->parent_id);
$this->assertEquals($image_id_1, $image_2->parent_id);
$this->assertEquals(["pbx"], $image_3->get_tag_array());
$this->assertEquals($image_3->id, $image_1->parent_id);
$this->assertEquals($image_1->id, $image_2->parent_id);
$this->assertNull($image_3->parent_id);
$this->assertTrue($image_1->has_children);
$this->assertFalse($image_2->has_children);
$this->assertTrue($image_3->has_children);
// Test settings parent:none
return [$image_1, $image_2, $image_3];
}
$this->get_page("post/view/$image_id_1");
$this->assert_title("Image $image_id_1: pbx");
/**
* @depends testSetChildByTag
*/
public function testRemoveParentByTag($imgs)
{
[$image_1, $image_2, $image_3] = $imgs;
$this->markTestIncomplete();
// check parent is set
$this->assertEquals($image_2->parent_id, $image_1->id);
$this->set_field("tag_edit__tags", "pbx parent:none");
$this->click("Set");
// un-set it
send_event(new TagSetEvent($image_2, ["pbx", "parent:none"]));
$this->assert_title("Image $image_id_1: pbx");
// refresh data from database
$image_2 = Image::by_id($image_2->id);
$image_1 = Image::by_id($image_id_1);
$image_2 = Image::by_id($image_id_2);
$image_3 = Image::by_id($image_id_3);
$this->assertNull($image_1->parent_id);
$this->assertEquals($image_id_1, $image_2->parent_id);
$this->assertNull($image_3->parent_id);
$this->assertTrue($image_1->has_children);
$this->assertFalse($image_2->has_children);
$this->assertFalse($image_3->has_children);
$this->log_out();
$this->log_in_as_admin();
$this->delete_image($image_id_1);
$this->delete_image($image_id_2);
$this->delete_image($image_id_3);
$this->log_out();
// check it was unset
$this->assertEquals(["pbx"], $image_2->get_tag_array());
$this->assertNull($image_2->parent_id);
}
}

View file

@ -30,6 +30,7 @@ class ResolutionLimitTest extends ShimmiePHPUnitTestCase
$this->log_in_as_user();
try {
$this->post_image("tests/pbx_screenshot.jpg", "pbx computer screenshot");
$this->assertTrue(false, "Invalid-size image was allowed");
} catch (UploadException $e) {
$this->assertEquals("Image too small", $e->getMessage());
}
@ -46,6 +47,7 @@ class ResolutionLimitTest extends ShimmiePHPUnitTestCase
try {
$this->post_image("tests/pbx_screenshot.jpg", "pbx computer screenshot");
$this->assertTrue(false, "Invalid-size image was allowed");
} catch (UploadException $e) {
$this->assertEquals("Image too large", $e->getMessage());
}
@ -62,6 +64,7 @@ class ResolutionLimitTest extends ShimmiePHPUnitTestCase
try {
$this->post_image("tests/pbx_screenshot.jpg", "pbx computer screenshot");
$this->assertTrue(false, "Invalid-size image was allowed");
} catch (UploadException $e) {
$this->assertEquals("Image needs to be in one of these ratios: 16:9", $e->getMessage());
}
@ -71,13 +74,13 @@ class ResolutionLimitTest extends ShimmiePHPUnitTestCase
# other extensions' test suites
public function tearDown(): void
{
parent::tearDown();
global $config;
$config->set_int("upload_min_height", -1);
$config->set_int("upload_min_width", -1);
$config->set_int("upload_max_height", -1);
$config->set_int("upload_max_width", -1);
$config->set_string("upload_ratios", "");
parent::tearDown();
}
}

View file

@ -15,7 +15,10 @@ class ShimmieApiTest extends ShimmiePHPUnitTestCase
$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");
$page = $this->get_page("api/shimmie/get_user/demo");
$this->assertEquals(200, $page->code);
//$this->get_page("api/shimmie/get_user?name=demo");
//$this->get_page("api/shimmie/get_user?id=2");

View file

@ -3,8 +3,7 @@ class XMLSitemapTest extends ShimmiePHPUnitTestCase
{
public function testBasic()
{
# this will implicitly check that there are no
# PHP-level error messages
$this->get_page('sitemap.xml');
$page = $this->get_page('sitemap.xml');
$this->assertEquals(200, $page->code);
}
}

View file

@ -64,11 +64,11 @@ class TagSetEvent extends Event
continue;
}
$ttpe = new TagTermParseEvent($tag, $this->image->id, false); //Only check for metatags, don't parse. Parsing is done after set_tags.
$ttpe = new TagTermCheckEvent($tag);
send_event($ttpe);
//seperate tags from metatags
if (!$ttpe->is_metatag()) {
if (!$ttpe->metatag) {
array_push($this->tags, $tag);
} else {
array_push($this->metatags, $tag);
@ -92,30 +92,35 @@ class LockSetEvent extends Event
}
}
/*
* TagTermParseEvent:
* Signal that a tag term needs parsing
/**
* Check whether or not a tag is a meta-tag
*/
class TagTermParseEvent extends Event
class TagTermCheckEvent extends Event
{
public $term = null; //tag
public $id = null; //image_id
/** @var bool */
public $metatag = false;
/** @var bool */
public $parse = true; //marks the tag to be parsed, and not just checked if valid metatag
public function __construct(string $term, int $id, bool $parse)
public function __construct(string $term)
{
parent::__construct();
$this->term = $term;
$this->id = $id;
$this->parse = $parse;
}
}
public function is_metatag(): bool
/**
* If a tag is a meta-tag, parse it
*/
class TagTermParseEvent extends Event
{
public $term = null;
public $image_id = null;
public function __construct(string $term, int $image_id)
{
return $this->metatag;
parent::__construct();
$this->term = $term;
$this->image_id = $image_id;
}
}
@ -245,17 +250,18 @@ class TagEdit extends Extension
$event->add_part($this->theme->get_lock_editor_html($event->image), 42);
}
public function onTagTermCheck(TagTermCheckEvent $event)
{
if (preg_match("/^source[=|:](.*)$/i", $event->term)) {
$event->metatag = true;
}
}
public function onTagTermParse(TagTermParseEvent $event)
{
$matches = [];
if (preg_match("/^source[=|:](.*)$/i", $event->term, $matches) && $event->parse) {
if (preg_match("/^source[=|:](.*)$/i", $event->term, $matches)) {
$source = ($matches[1] !== "none" ? $matches[1] : null);
send_event(new SourceSetEvent(Image::by_id($event->id), $source));
}
if (!empty($matches)) {
$event->metatag = true;
send_event(new SourceSetEvent(Image::by_id($event->image_id), $source));
}
}

View file

@ -20,7 +20,6 @@ class DataUploadEvent extends Event
/** @var bool */
public $merged = false;
/**
* Some data is being uploaded.
* This should be caught by a file handler.

View file

@ -12,7 +12,8 @@ class UploadTest extends ShimmiePHPUnitTestCase
public function testUpload()
{
$this->log_in_as_user();
$this->post_image("tests/pbx_screenshot.jpg", "pbx computer screenshot");
$image_id = $this->post_image("tests/pbx_screenshot.jpg", "pbx computer screenshot");
$this->assertGreaterThan(0, $image_id);
}
public function testRejectDupe()
@ -28,11 +29,8 @@ class UploadTest extends ShimmiePHPUnitTestCase
public function testRejectUnknownFiletype()
{
try {
$this->post_image("index.php", "test");
} catch (UploadException $e) {
$this->assertStringContainsString("Invalid or corrupted file", $e->getMessage());
}
$image_id = $this->post_image("index.php", "test");
$this->assertEquals(-1, $image_id); // no file handler claimed this
}
public function testRejectHuge()

View file

@ -35,9 +35,20 @@ $_tracer->end();
abstract class ShimmiePHPUnitTestCase extends \PHPUnit\Framework\TestCase
{
protected $anon_name = "anonymous";
protected $admin_name = "demo";
protected $user_name = "test";
protected static $anon_name = "anonymous";
protected static $admin_name = "demo";
protected static $user_name = "test";
protected $wipe_time = "test";
public static function setUpBeforeClass(): void
{
parent::setUpBeforeClass();
global $_tracer;
$_tracer->begin("Test Class");
self::create_user(self::$admin_name);
self::create_user(self::$user_name);
}
public function setUp(): void
{
@ -49,18 +60,16 @@ abstract class ShimmiePHPUnitTestCase extends \PHPUnit\Framework\TestCase
$this->markTestSkipped("$class not supported with this database");
}
$this->create_user($this->admin_name);
$this->create_user($this->user_name);
// If we have a parent test, don't wipe out the state they gave us
if (!$this->getDependencyInput()) {
// things to do after bootstrap and before request
// log in as anon
self::log_out();
// things to do after bootstrap and before request
// log in as anon
$this->log_out();
$_tracer->begin("tearDown");
foreach ($database->get_col("SELECT id FROM images") as $image_id) {
send_event(new ImageDeletionEvent(Image::by_id($image_id)));
foreach ($database->get_col("SELECT id FROM images") as $image_id) {
send_event(new ImageDeletionEvent(Image::by_id($image_id)));
}
}
$_tracer->end();
$_tracer->end();
$_tracer->begin("test");
@ -75,7 +84,14 @@ abstract class ShimmiePHPUnitTestCase extends \PHPUnit\Framework\TestCase
$_tracer->flush("tests/trace.json");
}
protected function create_user(string $name)
public static function tearDownAfterClass(): void
{
parent::tearDownAfterClass();
global $_tracer;
$_tracer->end();
}
protected static function create_user(string $name)
{
if (is_null(User::by_name($name))) {
$userPage = new UserPage();
@ -84,7 +100,7 @@ abstract class ShimmiePHPUnitTestCase extends \PHPUnit\Framework\TestCase
}
}
protected function get_page($page_name, $args=null)
protected static function get_page($page_name, $args=null)
{
// use a fresh page
global $page;
@ -101,7 +117,7 @@ abstract class ShimmiePHPUnitTestCase extends \PHPUnit\Framework\TestCase
return $page;
}
protected function post_page($page_name, $args=null)
protected static function post_page($page_name, $args=null)
{
// use a fresh page
global $page;
@ -186,23 +202,31 @@ abstract class ShimmiePHPUnitTestCase extends \PHPUnit\Framework\TestCase
$this->assertStringNotContainsString($content, $page->data);
}
protected function assert_search_results($tags, $results)
{
$images = Image::find_images(0, null, $tags);
$ids = [];
foreach ($images as $image) {
$ids[] = $image->id;
}
$this->assertEquals($results, $ids);
}
// user things
protected function log_in_as_admin()
protected static function log_in_as_admin()
{
send_event(new UserLoginEvent(User::by_name($this->admin_name)));
send_event(new UserLoginEvent(User::by_name(self::$admin_name)));
}
protected function log_in_as_user()
protected static function log_in_as_user()
{
send_event(new UserLoginEvent(User::by_name($this->user_name)));
send_event(new UserLoginEvent(User::by_name(self::$user_name)));
}
protected function log_out()
protected static function log_out()
{
global $config;
$user = User::by_id($config->get_int("anon_id", 0));
$this->assertNotNull($user);
send_event(new UserLoginEvent($user));
send_event(new UserLoginEvent(User::by_id($config->get_int("anon_id", 0))));
}
// post things