diff --git a/ext/admin/main.php b/ext/admin/main.php index 4ca59eb7..212b07fb 100644 --- a/ext/admin/main.php +++ b/ext/admin/main.php @@ -124,13 +124,13 @@ class AdminPage extends Extension } } - public function onPostListBuilding(PostListBuildingEvent $event) - { - global $user; - if ($user->can("manage_admintools") && !empty($event->search_terms)) { - $event->add_control($this->theme->dbq_html(Tag::implode($event->search_terms))); - } - } + // public function onPostListBuilding(PostListBuildingEvent $event) + // { + // global $user; + // if ($user->can("manage_admintools") && !empty($event->search_terms)) { + // $event->add_control($this->theme->dbq_html(Tag::implode($event->search_terms))); + // } + // } private function delete_by_query() { diff --git a/ext/bulk_actions/main.php b/ext/bulk_actions/main.php new file mode 100644 index 00000000..66ce1d6b --- /dev/null +++ b/ext/bulk_actions/main.php @@ -0,0 +1,228 @@ +, contributions by Shish and Agasa. + */ + + +class BulkActionBlockBuildingEvent extends Event { + /** @var array */ + public $actions = array(); + /** + * @param string $name + */ + public function add_action(String $action, String $confirmation_message = "", String $block = "", int $position = 40) { + if($block==null) + $block = ""; + + array_push($this->actions, array( + "block"=>$block, + "confirmation_message"=>$confirmation_message, + "action"=>$action, + "position"=>$position) + ); + } +} + +class BulkActionEvent extends Event { + public $action; + public $items; + public $page_request; + + function __construct (String $action, PageRequestEvent $pageRequestEvent, array $items) { + $this->action = $action; + $this->page_request = $pageRequestEvent; + $this->items = $items; + } + +} + +class BulkActions extends Extension +{ + public function onPostListBuilding(PostListBuildingEvent $event) + { + global $config, $page, $user; + + $this->theme->display_selector($page, $event, $config, Tag::implode($event->search_terms)); + } + + public function onBulkActionBlockBuilding(BulkActionBlockBuildingEvent $event) + { + global $user; + + if ($user->can("delete_image")) { + $event->add_action("Delete","Delete selected images?","",10); + } + + if ($user->can("bulk_edit_image_tag")) { + $event->add_action("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); + } + + } + + public function onBulkAction(BulkActionEvent $event) + { + global $user; + + switch($event->action) { + case "Delete": + if ($user->can("delete_image")) { + $this->delete_items($event->items); + } + break; + case "Tag": + if (!isset($_POST['bulk_tags'])) { + return; + } + if ($user->can("bulk_edit_image_tag")) { + $tags = $_POST['bulk_tags']; + $replace = false; + if(isset($_POST['bulk_tags_replace']) && $_POST['bulk_tags_replace']=="true") { + $replace = true; + } + + $this->tag_items($event->items, $tags, $replace); + } + break; + case "Set Source": + if (!isset($_POST['bulk_source'])) { + return; + } + if ($user->can("bulk_edit_image_source")) { + $source = $_POST['bulk_source']; + $this->set_source($event->items, $source); + } + break; + } + + } + + public function onPageRequest(PageRequestEvent $event) + { + global $page, $user; + if ($event->page_matches("bulk_action") && $user->is_admin()) { + if (!isset($_POST['bulk_action'])) { + return; + } + + $action = $_POST['bulk_action']; + + $items = []; + if(isset($_POST['bulk_selected_ids'])&&$_POST['bulk_selected_ids']!="") { + $data = json_decode($_POST['bulk_selected_ids']); + if(is_array($data)) { + foreach ($data as $id) { + if(is_numeric($id)) { + $item = Image::by_id(int_escape($id)); + array_push($items, $item); + } + } + } + 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; + while (true) { + $items = Image::find_images($n, 100, Tag::explode($query)); + if (count($items) == 0) { + break; + } + + reset($items); // rewind to first element in array. + $newEvent = new BulkActionEvent($action, $event, $items); + send_event($newEvent); + + $n += 100; + } + } + } + + + + $page->set_mode("redirect"); + if (!isset($_SERVER['HTTP_REFERER'])) { + $_SERVER['HTTP_REFERER'] = make_link(); + } + $page->set_redirect($_SERVER['HTTP_REFERER']); + } + } + + private function delete_items(array $items) { + $total = 0; + foreach ($items as $item) { + try { + send_event(new ImageDeletionEvent($item)); + $total++; + } catch(Exception $e) { + flash_message("Error while removing $item->id: ".$e->getMessage(), "error"); + } + } + + flash_message("Deleted $total items"); + + } + + private function tag_items(array $items, string $tags, bool $replace) { + $tags = Tag::explode($tags); + + $pos_tag_array = []; + $neg_tag_array = []; + foreach ($tags as $new_tag) { + if (strpos($new_tag, '-') === 0) { + $neg_tag_array[] = substr($new_tag, 1); + } else { + $pos_tag_array[] = $new_tag; + } + } + + $total = 0; + if ($replace) { + foreach ($items as $item) { + send_event(new TagSetEvent($item, $tags)); + $total++; + } + } else { + foreach ($items as $item) { + $img_tags = []; + if (!empty($neg_tag_array)) { + $img_tags = array_merge($pos_tag_array, $item->get_tag_array()); + $img_tags = array_diff($img_tags, $neg_tag_array); + } else { + $img_tags =array_merge($tags, $item->get_tag_array()); + } + send_event(new TagSetEvent($item, $img_tags)); + $total++; + } + } + + flash_message("Tagged $total items"); + } + + private function set_source(array $items, String $source) { + $total = 0; + foreach ($items as $item) { + try { + send_event(new SourceSetEvent($item, $source)); + $total++; + } catch(Exception $e) { + flash_message("Error while setting source for $item->id: ".$e->getMessage(), "error"); + } + } + + flash_message("Set source for $total items"); + + } +} diff --git a/ext/bulk_actions/script.js b/ext/bulk_actions/script.js new file mode 100644 index 00000000..f96466e1 --- /dev/null +++ b/ext/bulk_actions/script.js @@ -0,0 +1,197 @@ +/*jshint bitwise:true, curly:true, forin:false, noarg:true, noempty:true, nonew:true, undef:true, strict:false, browser:true, jquery:true */ + +var bulk_selector_active = false; +var bulk_selector_initialized = false; +var bulk_selector_valid = false; + +function validate_selections(form, confirmationMessage) { + var queryOnly = false; + if(bulk_selector_active) { + var data = get_selected_items(); + if(data.length==0) { + return false; + } + } else { + var query = $(form).find('input[name="bulk_query"]').val(); + + if (query == null || query == "") { + return false; + } else { + queryOnly = true; + } + } + + + if(confirmationMessage!=null&&confirmationMessage!="") { + return confirm(confirmationMessage); + } else if(queryOnly) { + var action = $(form).find('input[name="bulk_action"]').val(); + + return confirm("Perform bulk action \"" + action + "\" on all images matching the current search?"); + } + + return true; +} + + +function activate_bulk_selector () { + set_selected_items([]); + if(!bulk_selector_initialized) { + $("a.shm-thumb").each( + function (index, block) { + add_selector_button($(block)); + } + ); + } + $('#bulk_selector_controls').show(); + $('#bulk_selector_activate').hide(); + bulk_selector_active = true; + bulk_selector_initialized = true; +} + +function deactivate_bulk_selector() { + set_selected_items([]); + $('#bulk_selector_controls').hide(); + $('#bulk_selector_activate').show(); + bulk_selector_active = false; +} + +function get_selected_items() { + var data = $('#bulk_selected_ids').val(); + if(data==""||data==null) { + data = []; + } else { + data = JSON.parse(data); + } + return data; +} + +function set_selected_items(items) { + $("a.shm-thumb").removeClass('selected'); + + $(items).each( + function(index,item) { + $('a.shm-thumb[data-post-id="' + item + '"]').addClass('selected'); + } + ); + + $('input[name="bulk_selected_ids"]').val(JSON.stringify(items)); +} + +function select_item(id) { + var data = get_selected_items(); + if(!data.includes(id)) + data.push(id); + set_selected_items(data); +} + +function deselect_item(id) { + var data = get_selected_items(); + if(data.includes(id)) + data.splice(data.indexOf(id, 1)); + set_selected_items(data); +} + +function toggle_selection( id ) { + var data = get_selected_items(); + console.log(id); + if(data.includes(id)) { + data.splice(data.indexOf(id),1); + set_selected_items(data); + return false; + } else { + data.push(id); + set_selected_items(data); + return true; + } +} + + +function select_all() { + var items = []; + $("a.shm-thumb").each( + function ( index, block ) { + block = $(block); + var id = block.data("post-id"); + items.push(id); + } + ); + set_selected_items(items); +} + +function select_invert() { + var currentItems = get_selected_items(); + var items = []; + $("a.shm-thumb").each( + function ( index, block ) { + block = $(block); + var id = block.data("post-id"); + if(!currentItems.includes(id)) { + items.push(id); + } + } + ); + set_selected_items(items); +} + +function select_none() { + set_selected_items([]); +} + +function select_range(start, end) { + var data = get_selected_items(); + var selecting = false; + $("a.shm-thumb").each( + function ( index, block ) { + block = $(block); + var id = block.data("post-id"); + if(id==start) + selecting = true; + + if(selecting) { + if(!data.includes(id)) + data.push(id); + } + + if(id==end) { + selecting = false; + } + } + ); + set_selected_items(data); +} + +var last_clicked_item; + +function add_selector_button($block) { + var c = function(e) { + if(!bulk_selector_active) + return true; + + e.preventDefault(); + e.stopPropagation(); + + var id = $block.data("post-id"); + if(e.shiftKey) { + if(last_clicked_itemis_logged_in()) { + $event = new BulkActionBlockBuildingEvent(); + send_event($event); + + if(sizeof($event->actions)==0) + return; + + $body =" + + "; + } + usort($event->actions, array($this, "sort_blocks")); + + foreach($event->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() { + return "". + ""; + } + + public function render_source_input() { + return ""; + } + +} diff --git a/ext/rating/main.php b/ext/rating/main.php index eba2c262..34f67b39 100644 --- a/ext/rating/main.php +++ b/ext/rating/main.php @@ -73,13 +73,13 @@ class Ratings extends Extension $event->panel->add_block($sb); } - public function onPostListBuilding(PostListBuildingEvent $event) - { - global $user; - if ($user->is_admin() && !empty($event->search_terms)) { - $this->theme->display_bulk_rater(Tag::implode($event->search_terms)); - } - } + // public function onPostListBuilding(PostListBuildingEvent $event) + // { + // global $user; + // if ($user->is_admin() && !empty($event->search_terms)) { + // $this->theme->display_bulk_rater(Tag::implode($event->search_terms)); + // } + // } public function onDisplayingImage(DisplayingImageEvent $event) @@ -143,6 +143,35 @@ class Ratings extends Extension } } + public function onBulkActionBlockBuilding(BulkActionBlockBuildingEvent $event) + { + global $user; + + if ($user->is_admin()) { + $event->add_action("Set Rating","",$this->theme->get_selection_rater_html("bulk_rating")); + } + + } + + public function onBulkAction(BulkActionEvent $event) + { + global $user; + + switch($event->action) { + case "Set Rating": + if (!isset($_POST['bulk_rating'])) { + return; + } + if ($user->is_admin()) { + $rating = $_POST['bulk_rating']; + foreach ($event->items as $image) { + send_event(new RatingSetEvent($image, $rating)); + } + } + break; + } + } + public function onPageRequest(PageRequestEvent $event) { global $user, $page; diff --git a/ext/rating/theme.php b/ext/rating/theme.php index 241c20c7..67f85831 100644 --- a/ext/rating/theme.php +++ b/ext/rating/theme.php @@ -45,4 +45,13 @@ class RatingsTheme extends Themelet "; $page->add_block(new Block("List Controls", $html, "left")); } + + public function get_selection_rater_html(String $id = "select_rating") { + return ""; + } } diff --git a/ext/regen_thumb/main.php b/ext/regen_thumb/main.php index 5df24698..40a49487 100644 --- a/ext/regen_thumb/main.php +++ b/ext/regen_thumb/main.php @@ -15,14 +15,23 @@ class RegenThumb extends Extension { + public function regenerate_thumbnail($image) + { + global $database; + + send_event(new ThumbnailGenerationEvent($image->hash, $image->ext, true)); + $database->cache->delete("thumb-block:{$image->id}"); + } + public function onPageRequest(PageRequestEvent $event) { global $database, $page, $user; if ($event->page_matches("regen_thumb/one") && $user->can("delete_image") && isset($_POST['image_id'])) { $image = Image::by_id(int_escape($_POST['image_id'])); - send_event(new ThumbnailGenerationEvent($image->hash, $image->ext, true)); - $database->cache->delete("thumb-block:{$image->id}"); + + $this->regenerate_thumbnail($image); + $this->theme->display_results($page, $image); } if ($event->page_matches("regen_thumb/mass") && $user->can("delete_image") && isset($_POST['tags'])) { @@ -30,8 +39,7 @@ class RegenThumb extends Extension $images = Image::find_images(0, 10000, $tags); foreach ($images as $image) { - send_event(new ThumbnailGenerationEvent($image->hash, $image->ext, true)); - $database->cache->delete("thumb-block:{$image->id}"); + $this->regenerate_thumbnail($image); } $page->set_mode("redirect"); @@ -47,11 +55,40 @@ class RegenThumb extends Extension } } - public function onPostListBuilding(PostListBuildingEvent $event) + // public function onPostListBuilding(PostListBuildingEvent $event) + // { + // global $user; + // if ($user->can("delete_image") && !empty($event->search_terms)) { + // $event->add_control($this->theme->mtr_html(Tag::implode($event->search_terms))); + // } + // } + + public function onBulkActionBlockBuilding(BulkActionBlockBuildingEvent $event) { global $user; - if ($user->can("delete_image") && !empty($event->search_terms)) { - $event->add_control($this->theme->mtr_html(Tag::implode($event->search_terms))); + + if ($user->can("delete_image")) { + $event->add_action("Regen Thumbnails"); + } + + } + + public function onBulkAction(BulkActionEvent $event) + { + global $user; + + switch($event->action) { + case "Regen Thumbnails": + if ($user->can("delete_image")) { + $total = 0; + foreach ($event->items as $image) { + $this->regenerate_thumbnail($image); + $total++; + } + flash_message("Regenerated thumbnails for $total items"); + } + break; } } + } diff --git a/ext/tag_edit/main.php b/ext/tag_edit/main.php index 8a74750a..19f0dfa0 100644 --- a/ext/tag_edit/main.php +++ b/ext/tag_edit/main.php @@ -179,13 +179,13 @@ class TagEdit extends Extension } } - public function onPostListBuilding(PostListBuildingEvent $event) - { - global $user; - if ($user->can("bulk_edit_image_source") && !empty($event->search_terms)) { - $event->add_control($this->theme->mss_html(Tag::implode($event->search_terms))); - } - } + // public function onPostListBuilding(PostListBuildingEvent $event) + // { + // global $user; + // if ($user->can("bulk_edit_image_source") && !empty($event->search_terms)) { + // $event->add_control($this->theme->mss_html(Tag::implode($event->search_terms))); + // } + // } public function onImageInfoSet(ImageInfoSetEvent $event) {