[replace] split upload and replace completely, fixes #1001
This commit is contained in:
parent
a28fb66b91
commit
4c2d6d9ca4
12 changed files with 294 additions and 221 deletions
|
@ -309,35 +309,25 @@ abstract class DataHandlerExtension extends Extension
|
|||
throw new UploadException("Invalid or corrupted file");
|
||||
}
|
||||
|
||||
/* Check if we are replacing an image */
|
||||
if (!is_null($event->replace_id)) {
|
||||
$existing = Image::by_id($event->replace_id);
|
||||
if (is_null($existing)) {
|
||||
throw new UploadException("Post to replace does not exist!");
|
||||
$this->move_upload_to_archive($event);
|
||||
$image = $this->create_image_from_data(warehouse_path(Image::IMAGE_DIR, $event->hash), $event->metadata);
|
||||
|
||||
$existing = Image::by_hash($image->hash);
|
||||
if (!is_null($existing)) {
|
||||
$handler = $config->get_string(ImageConfig::UPLOAD_COLLISION_HANDLER);
|
||||
if ($handler == ImageConfig::COLLISION_MERGE) {
|
||||
$image = $existing;
|
||||
} else {
|
||||
throw new UploadException(">>{$existing->id} already has hash {$image->hash}");
|
||||
}
|
||||
send_event(new ImageReplaceEvent($existing, $event->tmpname));
|
||||
$event->images[] = $existing;
|
||||
} else {
|
||||
$this->move_upload_to_archive($event);
|
||||
$image = $this->create_image_from_data(warehouse_path(Image::IMAGE_DIR, $event->hash), $event->metadata);
|
||||
|
||||
$existing = Image::by_hash($image->hash);
|
||||
if (!is_null($existing)) {
|
||||
$handler = $config->get_string(ImageConfig::UPLOAD_COLLISION_HANDLER);
|
||||
if ($handler == ImageConfig::COLLISION_MERGE) {
|
||||
$image = $existing;
|
||||
} else {
|
||||
throw new UploadException(">>{$existing->id} already has hash {$image->hash}");
|
||||
}
|
||||
}
|
||||
|
||||
// ensure $image has a database-assigned ID number
|
||||
// before anything else happens
|
||||
$image->save_to_db();
|
||||
|
||||
$iae = send_event(new ImageAdditionEvent($image, $event->metadata, !is_null($existing)));
|
||||
$event->images[] = $iae->image;
|
||||
}
|
||||
|
||||
// ensure $image has a database-assigned ID number
|
||||
// before anything else happens
|
||||
$image->save_to_db();
|
||||
|
||||
$iae = send_event(new ImageAdditionEvent($image, $event->metadata, !is_null($existing)));
|
||||
$event->images[] = $iae->image;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -576,20 +576,27 @@ class Image
|
|||
$this->delete_tags_from_image();
|
||||
$database->execute("DELETE FROM images WHERE id=:id", ["id" => $this->id]);
|
||||
log_info("core_image", 'Deleted Post #'.$this->id.' ('.$this->hash.')');
|
||||
|
||||
unlink($this->get_image_filename());
|
||||
unlink($this->get_thumb_filename());
|
||||
$this->remove_image_only(quiet: true);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function removes an image (and thumbnail) from the DISK ONLY.
|
||||
* It DOES NOT remove anything from the database.
|
||||
*/
|
||||
public function remove_image_only(): void
|
||||
public function remove_image_only(bool $quiet=false): void
|
||||
{
|
||||
log_info("core_image", 'Removed Post File ('.$this->hash.')');
|
||||
@unlink($this->get_image_filename());
|
||||
@unlink($this->get_thumb_filename());
|
||||
$img_del = @unlink($this->get_image_filename());
|
||||
$thumb_del = @unlink($this->get_thumb_filename());
|
||||
if($img_del && $thumb_del) {
|
||||
if(!$quiet) {
|
||||
log_info("core_image", "Deleted files for Post #{$this->id} ({$this->hash})");
|
||||
}
|
||||
}
|
||||
else {
|
||||
$img = $img_del ? '' : ' image';
|
||||
$thumb = $thumb_del ? '' : ' thumbnail';
|
||||
log_error('core_image', "Failed to delete files for Post #{$this->id}{$img}{$thumb}");
|
||||
}
|
||||
}
|
||||
|
||||
public function parse_link_template(string $tmpl, int $n = 0): string
|
||||
|
|
|
@ -116,10 +116,6 @@ class ImageIO extends Extension
|
|||
if ($user->can(Permissions::DELETE_IMAGE)) {
|
||||
$event->add_part($this->theme->get_deleter_html($event->image->id));
|
||||
}
|
||||
/* In the future, could perhaps allow users to replace images that they own as well... */
|
||||
if ($user->can(Permissions::REPLACE_IMAGE)) {
|
||||
$event->add_part($this->theme->get_replace_html($event->image->id));
|
||||
}
|
||||
}
|
||||
|
||||
public function onCommand(CommandEvent $event)
|
||||
|
@ -141,43 +137,6 @@ class ImageIO extends Extension
|
|||
log_info("image", "Uploaded >>{$event->image->id} ({$event->image->hash})");
|
||||
}
|
||||
|
||||
public function onImageReplace(ImageReplaceEvent $event)
|
||||
{
|
||||
$image = $event->image;
|
||||
|
||||
try {
|
||||
$duplicate = Image::by_hash($event->new_hash);
|
||||
if (!is_null($duplicate) && $duplicate->id != $image->id) {
|
||||
throw new ImageReplaceException("A different post >>{$duplicate->id} already has hash {$duplicate->hash}");
|
||||
}
|
||||
|
||||
$image->remove_image_only(); // Actually delete the old image file from disk
|
||||
|
||||
$target = warehouse_path(Image::IMAGE_DIR, $event->new_hash);
|
||||
if (!@copy($event->tmp_filename, $target)) {
|
||||
$errors = error_get_last();
|
||||
throw new UploadException(
|
||||
"Failed to copy file from uploads ({$event->tmp_filename}) to archive ($target): ".
|
||||
"{$errors['type']} / {$errors['message']}"
|
||||
);
|
||||
}
|
||||
unlink($event->tmp_filename);
|
||||
|
||||
// update metadata and save metadata to DB
|
||||
$event->image->hash = $event->new_hash;
|
||||
$event->image->filesize = filesize($target);
|
||||
$event->image->set_mime(MimeType::get_for_file($target));
|
||||
send_event(new MediaCheckPropertiesEvent($image));
|
||||
$image->save_to_db();
|
||||
|
||||
send_event(new ThumbnailGenerationEvent($image));
|
||||
|
||||
log_info("image", "Replaced >>{$image->id} {$event->original_hash} with {$event->new_hash}");
|
||||
} catch (ImageReplaceException $e) {
|
||||
throw new UploadException($e->error);
|
||||
}
|
||||
}
|
||||
|
||||
public function onImageDeletion(ImageDeletionEvent $event)
|
||||
{
|
||||
$event->image->delete();
|
||||
|
|
|
@ -20,14 +20,4 @@ class ImageIOTheme extends Themelet
|
|||
INPUT(["type" => 'submit', "value" => 'Delete', "onclick" => 'return confirm("Delete the image?");', "id" => "image_delete_button"]),
|
||||
)."</span>";
|
||||
}
|
||||
|
||||
/**
|
||||
* Display link to replace the image
|
||||
*/
|
||||
public function get_replace_html(int $image_id): string
|
||||
{
|
||||
$form = SHM_FORM("replace/$image_id", "GET");
|
||||
$form->appendChild(INPUT(["type" => 'submit', "value" => 'Replace']));
|
||||
return (string)$form;
|
||||
}
|
||||
}
|
||||
|
|
20
ext/replace_file/info.php
Normal file
20
ext/replace_file/info.php
Normal file
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Shimmie2;
|
||||
|
||||
class ReplaceFileInfo extends ExtensionInfo
|
||||
{
|
||||
public const KEY = "replace_file";
|
||||
|
||||
public string $key = self::KEY;
|
||||
public string $name = "Replace File";
|
||||
public string $url = self::SHIMMIE_URL;
|
||||
public array $authors = self::SHISH_AUTHOR;
|
||||
public string $description = "Allows people to replace files for existing posts";
|
||||
|
||||
// Core because several other extensions depend on it, this could be
|
||||
// non-core if we had a way to specify dependencies dynamically
|
||||
public bool $core = true;
|
||||
}
|
90
ext/replace_file/main.php
Normal file
90
ext/replace_file/main.php
Normal file
|
@ -0,0 +1,90 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Shimmie2;
|
||||
|
||||
class ReplaceFile extends Extension
|
||||
{
|
||||
/** @var ReplaceFileTheme */
|
||||
protected Themelet $theme;
|
||||
|
||||
public function onPageRequest(PageRequestEvent $event)
|
||||
{
|
||||
global $cache, $page, $user;
|
||||
|
||||
if ($event->page_matches("replace")) {
|
||||
if (!$user->can(Permissions::REPLACE_IMAGE)) {
|
||||
$this->theme->display_error(403, "Error", "{$user->name} doesn't have permission to replace images");
|
||||
return;
|
||||
}
|
||||
|
||||
$image_id = int_escape($event->get_arg(0));
|
||||
$image = Image::by_id($image_id);
|
||||
if (is_null($image)) {
|
||||
throw new UploadException("Can not replace Post: No post with ID $image_id");
|
||||
}
|
||||
|
||||
if($event->method == "GET") {
|
||||
$this->theme->display_replace_page($page, $image_id);
|
||||
} elseif($event->method == "POST") {
|
||||
if (!empty($_POST["url"])) {
|
||||
$tmp_filename = tempnam(ini_get('upload_tmp_dir'), "shimmie_transload");
|
||||
fetch_url($_POST["url"], $tmp_filename);
|
||||
send_event(new ImageReplaceEvent($image, $tmp_filename));
|
||||
} elseif (count($_FILES) > 0) {
|
||||
send_event(new ImageReplaceEvent($image, $_FILES["data"]['tmp_name']));
|
||||
}
|
||||
if(!empty($_POST["source"])) {
|
||||
send_event(new SourceSetEvent($image, $_POST["source"]));
|
||||
}
|
||||
$cache->delete("thumb-block:{$image_id}");
|
||||
$page->set_mode(PageMode::REDIRECT);
|
||||
$page->set_redirect(make_link("post/view/$image_id"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function onImageAdminBlockBuilding(ImageAdminBlockBuildingEvent $event)
|
||||
{
|
||||
global $user;
|
||||
|
||||
/* In the future, could perhaps allow users to replace images that they own as well... */
|
||||
if ($user->can(Permissions::REPLACE_IMAGE)) {
|
||||
$event->add_part($this->theme->get_replace_html($event->image->id));
|
||||
}
|
||||
}
|
||||
|
||||
public function onImageReplace(ImageReplaceEvent $event)
|
||||
{
|
||||
$image = $event->image;
|
||||
|
||||
$duplicate = Image::by_hash($event->new_hash);
|
||||
if (!is_null($duplicate) && $duplicate->id != $image->id) {
|
||||
throw new ImageReplaceException("A different post >>{$duplicate->id} already has hash {$duplicate->hash}");
|
||||
}
|
||||
|
||||
$image->remove_image_only(); // Actually delete the old image file from disk
|
||||
|
||||
$target = warehouse_path(Image::IMAGE_DIR, $event->new_hash);
|
||||
if (!@copy($event->tmp_filename, $target)) {
|
||||
$errors = error_get_last();
|
||||
throw new UploadException(
|
||||
"Failed to copy file from uploads ({$event->tmp_filename}) to archive ($target): ".
|
||||
"{$errors['type']} / {$errors['message']}"
|
||||
);
|
||||
}
|
||||
unlink($event->tmp_filename);
|
||||
|
||||
// update metadata and save metadata to DB
|
||||
$event->image->hash = $event->new_hash;
|
||||
$event->image->filesize = filesize($target);
|
||||
$event->image->set_mime(MimeType::get_for_file($target));
|
||||
send_event(new MediaCheckPropertiesEvent($image));
|
||||
$image->save_to_db();
|
||||
|
||||
send_event(new ThumbnailGenerationEvent($image));
|
||||
|
||||
log_info("image", "Replaced >>{$image->id} {$event->original_hash} with {$event->new_hash}");
|
||||
}
|
||||
}
|
68
ext/replace_file/test.php
Normal file
68
ext/replace_file/test.php
Normal file
|
@ -0,0 +1,68 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Shimmie2;
|
||||
|
||||
class ReplaceFileTest extends ShimmiePHPUnitTestCase
|
||||
{
|
||||
public function testReplacePage()
|
||||
{
|
||||
$this->log_in_as_admin();
|
||||
$image_id = $this->post_image("tests/pbx_screenshot.jpg", "pbx computer screenshot");
|
||||
$this->get_page("replace/$image_id");
|
||||
$this->assert_title("Replace File");
|
||||
}
|
||||
public function testReplace()
|
||||
{
|
||||
global $database;
|
||||
$this->log_in_as_admin();
|
||||
|
||||
// upload an image
|
||||
$image_id = $this->post_image("tests/pbx_screenshot.jpg", "pbx computer screenshot");
|
||||
|
||||
// check that the image is original
|
||||
$image = Image::by_id($image_id);
|
||||
$old_hash = md5_file("tests/pbx_screenshot.jpg");
|
||||
//$this->assertEquals("pbx_screenshot.jpg", $image->filename);
|
||||
$this->assertEquals("image/jpeg", $image->get_mime());
|
||||
$this->assertEquals(19774, $image->filesize);
|
||||
$this->assertEquals(640, $image->width);
|
||||
$this->assertEquals($old_hash, $image->hash);
|
||||
|
||||
// replace it
|
||||
// create a copy because the file is deleted after upload
|
||||
$tmpfile = tempnam(sys_get_temp_dir(), "shimmie_test");
|
||||
copy("tests/favicon.png", $tmpfile);
|
||||
$new_hash = md5_file($tmpfile);
|
||||
$_FILES = [
|
||||
'data' => [
|
||||
'name' => 'favicon.png',
|
||||
'type' => 'image/png',
|
||||
'tmp_name' => $tmpfile,
|
||||
'error' => 0,
|
||||
'size' => 246,
|
||||
]
|
||||
];
|
||||
$page = $this->post_page("replace/$image_id");
|
||||
$this->assert_response(302);
|
||||
$this->assertEquals("/test/post/view/$image_id", $page->redirect);
|
||||
|
||||
// check that there's still one image
|
||||
$this->assertEquals(1, $database->get_one("SELECT COUNT(*) FROM images"));
|
||||
|
||||
// check that the image was replaced
|
||||
$image = Image::by_id($image_id);
|
||||
// $this->assertEquals("favicon.png", $image->filename); // TODO should we update filename?
|
||||
$this->assertEquals("image/png", $image->get_mime());
|
||||
$this->assertEquals(246, $image->filesize);
|
||||
$this->assertEquals(16, $image->width);
|
||||
$this->assertEquals(md5_file("tests/favicon.png"), $image->hash);
|
||||
|
||||
// check that new files exist and old files don't
|
||||
$this->assertFalse(file_exists(warehouse_path(Image::IMAGE_DIR, $old_hash)));
|
||||
$this->assertFalse(file_exists(warehouse_path(Image::THUMBNAIL_DIR, $old_hash)));
|
||||
$this->assertTrue(file_exists(warehouse_path(Image::IMAGE_DIR, $new_hash)));
|
||||
$this->assertTrue(file_exists(warehouse_path(Image::THUMBNAIL_DIR, $new_hash)));
|
||||
}
|
||||
}
|
80
ext/replace_file/theme.php
Normal file
80
ext/replace_file/theme.php
Normal file
|
@ -0,0 +1,80 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Shimmie2;
|
||||
|
||||
use function MicroHTML\{TABLE,TR,TD};
|
||||
use function MicroHTML\SMALL;
|
||||
use function MicroHTML\INPUT;
|
||||
use function MicroHTML\emptyHTML;
|
||||
use function MicroHTML\BR;
|
||||
use function MicroHTML\P;
|
||||
|
||||
class ReplaceFileTheme extends Themelet
|
||||
{
|
||||
/**
|
||||
* Only allows 1 file to be uploaded - for replacing another image file.
|
||||
*/
|
||||
public function display_replace_page(Page $page, int $image_id)
|
||||
{
|
||||
global $config, $page;
|
||||
$tl_enabled = ($config->get_string(UploadConfig::TRANSLOAD_ENGINE, "none") != "none");
|
||||
$accept = $this->get_accept();
|
||||
|
||||
$max_size = $config->get_int(UploadConfig::SIZE);
|
||||
$max_kb = to_shorthand_int($max_size);
|
||||
|
||||
$image = Image::by_id($image_id);
|
||||
$thumbnail = $this->build_thumb_html($image);
|
||||
|
||||
$form = SHM_FORM("replace/".$image_id, "POST", true);
|
||||
$form->appendChild(emptyHTML(
|
||||
TABLE(
|
||||
["id" => "large_upload_form", "class" => "form"],
|
||||
TR(
|
||||
TD("File"),
|
||||
TD(INPUT(["name" => "data", "type" => "file", "accept" => $accept]))
|
||||
),
|
||||
$tl_enabled ? TR(
|
||||
TD("or URL"),
|
||||
TD(INPUT(["name" => "url", "type" => "text", "value" => @$_GET['url']]))
|
||||
) : null,
|
||||
TR(TD("Source"), TD(["colspan" => 3], INPUT(["name" => "source", "type" => "text"]))),
|
||||
TR(TD(["colspan" => 4], INPUT(["id" => "uploadbutton", "type" => "submit", "value" => "Post"]))),
|
||||
)
|
||||
));
|
||||
|
||||
$html = emptyHTML(
|
||||
P(
|
||||
"Replacing Post ID $image_id",
|
||||
BR(),
|
||||
"Please note: You will have to refresh the post page, or empty your browser cache."
|
||||
),
|
||||
$thumbnail,
|
||||
BR(),
|
||||
$form,
|
||||
$max_size > 0 ? SMALL("(Max file size is $max_kb)") : null,
|
||||
);
|
||||
|
||||
$page->set_title("Replace File");
|
||||
$page->set_heading("Replace File");
|
||||
$page->add_block(new NavBlock());
|
||||
$page->add_block(new Block("Upload Replacement File", $html, "main", 20));
|
||||
}
|
||||
|
||||
/**
|
||||
* Display link to replace the image
|
||||
*/
|
||||
public function get_replace_html(int $image_id): string
|
||||
{
|
||||
$form = SHM_FORM("replace/$image_id", "GET");
|
||||
$form->appendChild(INPUT(["type" => 'submit', "value" => 'Replace']));
|
||||
return (string)$form;
|
||||
}
|
||||
|
||||
protected function get_accept(): string
|
||||
{
|
||||
return ".".join(",.", DataHandlerExtension::get_all_supported_exts());
|
||||
}
|
||||
}
|
|
@ -182,13 +182,6 @@ class TagEdit extends Extension
|
|||
}
|
||||
}
|
||||
|
||||
public function onImageReplace(ImageReplaceEvent $event)
|
||||
{
|
||||
if(!empty($_POST['source'])) {
|
||||
send_event(new SourceSetEvent($event->image, $_POST['source']));
|
||||
}
|
||||
}
|
||||
|
||||
public function onImageInfoSet(ImageInfoSetEvent $event)
|
||||
{
|
||||
global $page, $user;
|
||||
|
|
|
@ -27,7 +27,6 @@ class DataUploadEvent extends Event
|
|||
public function __construct(
|
||||
public string $tmpname,
|
||||
public array $metadata,
|
||||
public ?int $replace_id = null
|
||||
) {
|
||||
parent::__construct();
|
||||
|
||||
|
@ -212,35 +211,7 @@ class Upload extends Extension
|
|||
}
|
||||
}
|
||||
|
||||
if ($event->page_matches("replace")) {
|
||||
if (!$user->can(Permissions::REPLACE_IMAGE)) {
|
||||
$this->theme->display_error(403, "Error", "{$user->name} doesn't have permission to replace images");
|
||||
return;
|
||||
}
|
||||
if ($this->is_full) {
|
||||
$this->theme->display_error(507, "Error", "Can't replace images: disk nearly full");
|
||||
return;
|
||||
}
|
||||
|
||||
$image_id = int_escape($event->get_arg(0));
|
||||
$image_old = Image::by_id($image_id);
|
||||
if (is_null($image_old)) {
|
||||
throw new UploadException("Can not replace Post: No post with ID $image_id");
|
||||
}
|
||||
|
||||
if($event->method == "GET") {
|
||||
$this->theme->display_replace_page($page, $image_id);
|
||||
} elseif($event->method == "POST") {
|
||||
$results = [];
|
||||
if (!empty($_POST["url"])) {
|
||||
$results = $this->try_transload($_POST["url"], [], $_POST['source'] ?? null, $image_id);
|
||||
} elseif (count($_FILES) > 0) {
|
||||
$results = $this->try_upload($_FILES["data"], [], $_POST['source'] ?? null, $image_id);
|
||||
}
|
||||
$cache->delete("thumb-block:{$image_id}");
|
||||
$this->theme->display_upload_status($page, $results);
|
||||
}
|
||||
} elseif ($event->page_matches("upload")) {
|
||||
if ($event->page_matches("upload")) {
|
||||
if (!$user->can(Permissions::CREATE_IMAGE)) {
|
||||
$this->theme->display_error(403, "Error", "{$user->name} doesn't have permission to upload images");
|
||||
return;
|
||||
|
@ -342,7 +313,7 @@ class Upload extends Extension
|
|||
* @param string[] $tags
|
||||
* @return UploadResult[]
|
||||
*/
|
||||
private function try_upload(array $file, array $tags, ?string $source = null, ?int $replace_id = null): array
|
||||
private function try_upload(array $file, array $tags, ?string $source = null): array
|
||||
{
|
||||
global $page, $config;
|
||||
|
||||
|
@ -376,7 +347,7 @@ class Upload extends Extension
|
|||
$metadata['tags'] = $tags;
|
||||
$metadata['source'] = $source;
|
||||
|
||||
$event = new DataUploadEvent($tmp_name, $metadata, $replace_id);
|
||||
$event = new DataUploadEvent($tmp_name, $metadata);
|
||||
send_event($event);
|
||||
if (count($event->images) == 0) {
|
||||
throw new UploadException("MIME type not supported: " . $event->mime);
|
||||
|
@ -395,7 +366,7 @@ class Upload extends Extension
|
|||
/**
|
||||
* @return UploadResult[]
|
||||
*/
|
||||
private function try_transload(string $url, array $tags, string $source = null, ?int $replace_id = null): array
|
||||
private function try_transload(string $url, array $tags, string $source = null): array
|
||||
{
|
||||
global $page, $config, $user;
|
||||
|
||||
|
@ -431,7 +402,7 @@ class Upload extends Extension
|
|||
}
|
||||
|
||||
// Upload file
|
||||
$event = new DataUploadEvent($tmp_filename, $metadata, $replace_id);
|
||||
$event = new DataUploadEvent($tmp_filename, $metadata);
|
||||
send_event($event);
|
||||
if (count($event->images) == 0) {
|
||||
throw new UploadException("File type not supported: " . $event->mime);
|
||||
|
|
|
@ -50,42 +50,6 @@ class UploadTest extends ShimmiePHPUnitTestCase
|
|||
$this->assertEquals(4, $database->get_one("SELECT COUNT(*) FROM images"));
|
||||
}
|
||||
|
||||
public function testRawReplace()
|
||||
{
|
||||
global $database;
|
||||
|
||||
$this->log_in_as_admin();
|
||||
$image_id = $this->post_image("tests/pbx_screenshot.jpg", "pbx computer screenshot");
|
||||
$original_posted = $database->get_one("SELECT posted FROM images WHERE id = $image_id");
|
||||
|
||||
sleep(1); // make sure the timestamp changes (see bug #903)
|
||||
|
||||
// create a copy because the file is deleted after upload
|
||||
$tmpfile = tempnam(sys_get_temp_dir(), "shimmie_test");
|
||||
copy("tests/bedroom_workshop.jpg", $tmpfile);
|
||||
|
||||
$_FILES = [
|
||||
'data' => [
|
||||
'name' => ['puppy-hugs.jpg'],
|
||||
'type' => ['image/jpeg'],
|
||||
'tmp_name' => [$tmpfile],
|
||||
'error' => [0],
|
||||
'size' => [271386],
|
||||
]
|
||||
];
|
||||
|
||||
$page = $this->post_page("replace/$image_id");
|
||||
$this->assert_response(302);
|
||||
$this->assertEquals("/test/post/view/$image_id", $page->redirect);
|
||||
$new_posted = $database->get_one("SELECT posted FROM images WHERE id = $image_id");
|
||||
|
||||
$this->assertEquals(1, $database->get_one("SELECT COUNT(*) FROM images"));
|
||||
|
||||
// check that the original timestamp is left alone, despite the
|
||||
// file being replaced (see bug #903)
|
||||
$this->assertEquals($original_posted, $new_posted);
|
||||
}
|
||||
|
||||
public function testUpload()
|
||||
{
|
||||
$this->log_in_as_user();
|
||||
|
|
|
@ -209,64 +209,6 @@ class UploadTheme extends Themelet
|
|||
return emptyHTML($html1, $html2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Only allows 1 file to be uploaded - for replacing another image file.
|
||||
*/
|
||||
public function display_replace_page(Page $page, int $image_id)
|
||||
{
|
||||
global $config, $page;
|
||||
$tl_enabled = ($config->get_string(UploadConfig::TRANSLOAD_ENGINE, "none") != "none");
|
||||
$accept = $this->get_accept();
|
||||
|
||||
$upload_list = emptyHTML(
|
||||
TR(
|
||||
TD("File"),
|
||||
TD(INPUT(["name" => "data[]", "type" => "file", "accept" => $accept]))
|
||||
)
|
||||
);
|
||||
if ($tl_enabled) {
|
||||
$upload_list->appendChild(
|
||||
TR(
|
||||
TD("or URL"),
|
||||
TD(INPUT(["name" => "url", "type" => "text", "value" => @$_GET['url']]))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$max_size = $config->get_int(UploadConfig::SIZE);
|
||||
$max_kb = to_shorthand_int($max_size);
|
||||
|
||||
$image = Image::by_id($image_id);
|
||||
$thumbnail = $this->build_thumb_html($image);
|
||||
|
||||
$form = SHM_FORM("replace/".$image_id, "POST", true);
|
||||
$form->appendChild(emptyHTML(
|
||||
TABLE(
|
||||
["id" => "large_upload_form", "class" => "form"],
|
||||
$upload_list,
|
||||
TR(TD("Source"), TD(["colspan" => 3], INPUT(["name" => "source", "type" => "text"]))),
|
||||
TR(TD(["colspan" => 4], INPUT(["id" => "uploadbutton", "type" => "submit", "value" => "Post"]))),
|
||||
)
|
||||
));
|
||||
|
||||
$html = emptyHTML(
|
||||
P(
|
||||
"Replacing Post ID $image_id",
|
||||
BR(),
|
||||
"Please note: You will have to refresh the post page, or empty your browser cache."
|
||||
),
|
||||
$thumbnail,
|
||||
BR(),
|
||||
$form,
|
||||
$max_size > 0 ? SMALL("(Max file size is $max_kb)") : null,
|
||||
);
|
||||
|
||||
$page->set_title("Replace Post");
|
||||
$page->set_heading("Replace Post");
|
||||
$page->add_block(new NavBlock());
|
||||
$page->add_block(new Block("Upload Replacement Post", $html, "main", 20));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param UploadResult[] $results
|
||||
*/
|
||||
|
@ -337,7 +279,6 @@ class UploadTheme extends Themelet
|
|||
NOSCRIPT(BR(), A(["href" => make_link("upload")], "Larger Form"))
|
||||
);
|
||||
}
|
||||
|
||||
protected function get_accept(): string
|
||||
{
|
||||
return ".".join(",.", DataHandlerExtension::get_all_supported_exts());
|
||||
|
|
Reference in a new issue