diff --git a/core/imageboard/image.php b/core/imageboard/image.php index 400f1821..804bc834 100644 --- a/core/imageboard/image.php +++ b/core/imageboard/image.php @@ -145,6 +145,51 @@ class Image return $images; } + /** + * Search for an array of image IDs + * + * #param string[] $tags + * #return int[] + */ + public static function find_image_ids(int $start, int $limit, array $tags=[]): array + { + global $database, $user, $config; + + $images = []; + + if ($start < 0) { + $start = 0; + } + if ($limit < 1) { + $limit = 1; + } + + if (SPEED_HAX) { + if (!$user->can("big_search") and count($tags) > 3) { + throw new SCoreException("Anonymous users may only search for up to 3 tags at a time"); + } + } + + $result = null; + if (SEARCH_ACCEL) { + $result = Image::get_accelerated_result($tags, $start, $limit); + } + + if (!$result) { + $querylet = Image::build_search_querylet($tags); + $querylet->append(new Querylet(" ORDER BY ".(Image::$order_sql ?: "images.".$config->get_string("index_order")))); + $querylet->append(new Querylet(" LIMIT :limit OFFSET :offset", ["limit"=>$limit, "offset"=>$start])); + #var_dump($querylet->sql); var_dump($querylet->variables); + $result = $database->execute($querylet->sql, $querylet->variables); + } + + while ($row = $result->fetch()) { + $images[] = $row["id"]; + } + Image::$order_sql = null; + return $images; + } + /* * Accelerator stuff */ diff --git a/ext/bulk_actions/main.php b/ext/bulk_actions/main.php index 2ab4d4d7..291dd513 100644 --- a/ext/bulk_actions/main.php +++ b/ext/bulk_actions/main.php @@ -14,7 +14,7 @@ class BulkActionBlockBuildingEvent extends Event /** @var array */ public $actions = array(); - public function add_action(String $action, String $confirmation_message = "", String $block = "", int $position = 40) + public function add_action(String $action, string $button_text, String $confirmation_message = "", String $block = "", int $position = 40) { if ($block == null) $block = ""; @@ -25,6 +25,7 @@ class BulkActionBlockBuildingEvent extends Event "block" => $block, "confirmation_message" => $confirmation_message, "action" => $action, + "button_text" => $button_text, "position" => $position ) ); @@ -33,17 +34,18 @@ class BulkActionBlockBuildingEvent extends Event class BulkActionEvent extends Event { + /** @var string */ public $action; + /** @var array */ public $items; + /** @var PageRequestEvent */ public $page_request; - public $running_total; - function __construct(String $action, PageRequestEvent $pageRequestEvent, array $items, int $running_total = 0) + function __construct(String $action, PageRequestEvent $pageRequestEvent, array $items) { $this->action = $action; $this->page_request = $pageRequestEvent; $this->items = $items; - $this->running_total = $running_total; } } @@ -53,7 +55,17 @@ class BulkActions extends Extension { global $config, $page, $user; - $this->theme->display_selector($page, $event, $config, Tag::implode($event->search_terms)); + if ($user->is_logged_in()) { + $babbe = new BulkActionBlockBuildingEvent(); + send_event($babbe); + + if (sizeof($babbe->actions) == 0) + return; + + usort($babbe->actions, array($this, "sort_blocks")); + + $this->theme->display_selector($page, $babbe->actions, Tag::implode($event->search_terms)); + } } public function onBulkActionBlockBuilding(BulkActionBlockBuildingEvent $event) @@ -61,15 +73,15 @@ class BulkActions extends Extension global $user; if ($user->can("delete_image")) { - $event->add_action("Delete", "Delete selected images?", "", 10); + $event->add_action("bulk_delete","Delete", "Delete selected images?", "", 10); } if ($user->can("bulk_edit_image_tag")) { - $event->add_action("Tag", "", $this->theme->render_tag_input(), 10); + $event->add_action("bulk_tag","Tag", "", $this->theme->render_tag_input(), 10); } if ($user->can("bulk_edit_image_source")) { - $event->add_action("Set Source", "", $this->theme->render_source_input(), 10); + $event->add_action("bulk_source","Set Source", "", $this->theme->render_source_input(), 10); } } @@ -78,13 +90,13 @@ class BulkActions extends Extension global $user; switch ($event->action) { - case "Delete": + case "bulk_delete": if ($user->can("delete_image")) { - $event->running_total += $this->delete_items($event->items); - flash_message("Deleted $event->running_total items"); + $i = $this->delete_items($event->items); + flash_message("Deleted $i items"); } break; - case "Tag": + case "bulk_tag": if (!isset($_POST['bulk_tags'])) { return; } @@ -95,18 +107,18 @@ class BulkActions extends Extension $replace = true; } - $event->running_total += $this->tag_items($event->items, $tags, $replace); - flash_message("Tagged $event->running_total items"); + $i= $this->tag_items($event->items, $tags, $replace); + flash_message("Tagged $i items"); } break; - case "Set Source": + case "bulk_source": if (!isset($_POST['bulk_source'])) { return; } if ($user->can("bulk_edit_image_source")) { $source = $_POST['bulk_source']; - $event->running_total += $this->set_source($event->items, $source); - flash_message("Set source for $event->running_total items"); + $i = $this->set_source($event->items, $source); + flash_message("Set source for $i items"); } break; } @@ -128,35 +140,33 @@ class BulkActions extends Extension if (is_array($data)) { foreach ($data as $id) { if (is_numeric($id)) { - $item = Image::by_id(int_escape($id)); - array_push($items, $item); + array_push($items, int_escape($id)); } } } - if (sizeof($items) > 0) { - reset($items); // rewind to first element in array. - $newEvent = new BulkActionEvent($action, $event, $items); - send_event($newEvent); - } } else if (isset($_POST['bulk_query']) && $_POST['bulk_query'] != "") { $query = $_POST['bulk_query']; if ($query != null && $query != "") { $n = 0; + $tags = Tag::explode($query); while (true) { - $items = Image::find_images($n, 100, Tag::explode($query)); - if (count($items) == 0) { + $results = Image::find_image_ids($n, 100, $tags); + if (count($results) == 0) { break; } - reset($items); // rewind to first element in array. - $newEvent = new BulkActionEvent($action, $event, $items, $n); - send_event($newEvent); - - $n = $newEvent->running_total; + reset($results); // rewind to first element in array. + $items = array_merge($items, $results); + $n += count($results); } } } + if (sizeof($items) > 0) { + reset($items); // rewind to first element in array. + $newEvent = new BulkActionEvent($action, $event, $items); + send_event($newEvent); + } $page->set_mode("redirect"); @@ -167,15 +177,25 @@ class BulkActions extends Extension } } + private function sort_blocks($a, $b) + { + return $a["position"] - $b["position"]; + } + private function delete_items(array $items): int { $total = 0; - foreach ($items as $item) { + foreach ($items as $id) { try { - send_event(new ImageDeletionEvent($item)); + $image = Image::by_id($id); + if($image==null) { + continue; + } + + send_event(new ImageDeletionEvent($image)); $total++; } catch (Exception $e) { - flash_message("Error while removing $item->id: " . $e->getMessage(), "error"); + flash_message("Error while removing $id: " . $e->getMessage(), "error"); } } return $total; @@ -197,20 +217,30 @@ class BulkActions extends Extension $total = 0; if ($replace) { - foreach ($items as $item) { - send_event(new TagSetEvent($item, $tags)); + foreach ($items as $id) { + $image = Image::by_id($id); + if($image==null) { + continue; + } + + send_event(new TagSetEvent($image, $tags)); $total++; } } else { - foreach ($items as $item) { + foreach ($items as $id) { + $image = Image::by_id($id); + if($image==null) { + continue; + } + $img_tags = []; if (!empty($neg_tag_array)) { - $img_tags = array_merge($pos_tag_array, $item->get_tag_array()); + $img_tags = array_merge($pos_tag_array, $image->get_tag_array()); $img_tags = array_diff($img_tags, $neg_tag_array); } else { - $img_tags = array_merge($tags, $item->get_tag_array()); + $img_tags = array_merge($tags, $image->get_tag_array()); } - send_event(new TagSetEvent($item, $img_tags)); + send_event(new TagSetEvent($image, $img_tags)); $total++; } } @@ -221,12 +251,17 @@ class BulkActions extends Extension private function set_source(array $items, String $source): int { $total = 0; - foreach ($items as $item) { + foreach ($items as $id) { try { - send_event(new SourceSetEvent($item, $source)); + $image = Image::by_id($id); + if($image==null) { + continue; + } + + send_event(new SourceSetEvent($image, $source)); $total++; } catch (Exception $e) { - flash_message("Error while setting source for $item->id: " . $e->getMessage(), "error"); + flash_message("Error while setting source for $id: " . $e->getMessage(), "error"); } } diff --git a/ext/bulk_actions/script.js b/ext/bulk_actions/script.js index f96466e1..b5e73f8b 100644 --- a/ext/bulk_actions/script.js +++ b/ext/bulk_actions/script.js @@ -25,7 +25,7 @@ function validate_selections(form, confirmationMessage) { if(confirmationMessage!=null&&confirmationMessage!="") { return confirm(confirmationMessage); } else if(queryOnly) { - var action = $(form).find('input[name="bulk_action"]').val(); + var action = $(form).find('input[name="submit_button"]').val(); return confirm("Perform bulk action \"" + action + "\" on all images matching the current search?"); } diff --git a/ext/bulk_actions/theme.php b/ext/bulk_actions/theme.php index a6c3ad3c..b0c06856 100644 --- a/ext/bulk_actions/theme.php +++ b/ext/bulk_actions/theme.php @@ -2,64 +2,51 @@ class BulkActionsTheme extends Themelet { - private function sort_blocks($a, $b) - { - return $a["position"] - $b["position"]; - } - public function display_selector(Page $page, Event $event, $config, $query) + + public function display_selector(Page $page, $actions, $query) { global $user; + $body = " + + "; - } - $block = new Block("Bulk Actions", $body, "left", 30); - $page->add_block($block); + if ($hasQuery) { + $body .= ""; } + + foreach ($actions as $action) { + $body .= "
" . make_form(make_link("bulk_action"), "POST", False, "", "return validate_selections(this,'" . html_escape($action["confirmation_message"]) . "');") . + "" . + "" . + "" . + $action["block"] . + "" . + "
"; + } + + if (!$hasQuery) { + $body .= ""; + } + $block = new Block("Bulk Actions", $body, "left", 30); + $page->add_block($block); } public function render_tag_input() diff --git a/ext/rating/main.php b/ext/rating/main.php index d99fa8d8..948e4b1a 100644 --- a/ext/rating/main.php +++ b/ext/rating/main.php @@ -170,7 +170,7 @@ class Ratings extends Extension global $user; if ($user->is_admin()) { - $event->add_action("Set Rating","",$this->theme->get_selection_rater_html("bulk_rating")); + $event->add_action("bulk_rate","Set Rating","",$this->theme->get_selection_rater_html("bulk_rating")); } } @@ -180,16 +180,23 @@ class Ratings extends Extension global $user; switch($event->action) { - case "Set Rating": + case "bulk_rate": if (!isset($_POST['bulk_rating'])) { return; } if ($user->is_admin()) { $rating = $_POST['bulk_rating']; - foreach ($event->items as $image) { + $total = 0; + foreach ($event->items as $id) { + $image = Image::by_id($id); + if($image==null) { + continue; + } + send_event(new RatingSetEvent($image, $rating)); - $event->running_total++; + $total++; } + flash_message("Rating set for $total items"); } break; } diff --git a/ext/regen_thumb/main.php b/ext/regen_thumb/main.php index 7fcff488..0a0e8963 100644 --- a/ext/regen_thumb/main.php +++ b/ext/regen_thumb/main.php @@ -69,7 +69,7 @@ class RegenThumb extends Extension global $user; if ($user->can("delete_image")) { - $event->add_action("Regen Thumbnails","",$this->theme->bulk_html()); + $event->add_action("bulk_regen","Regen Thumbnails","",$this->theme->bulk_html()); } } @@ -79,7 +79,7 @@ class RegenThumb extends Extension global $user; switch($event->action) { - case "Regen Thumbnails": + case "bulk_regen": if ($user->can("delete_image")) { $force = true; if(isset($_POST["bulk_regen_thumb_missing_only"]) @@ -88,13 +88,18 @@ class RegenThumb extends Extension $force=false; } - - foreach ($event->items as $image) { + $total = 0; + foreach ($event->items as $id) { + $image = Image::by_id($id); + if($image==null) { + continue; + } + if($this->regenerate_thumbnail($image, $force)) { - $event->running_total++; + $total++; } } - flash_message("Regenerated thumbnails for $event->running_total items"); + flash_message("Regenerated thumbnails for $total items"); } break; }