2021-12-14 18:32:47 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
declare(strict_types=1);
|
2019-10-14 18:35:33 +00:00
|
|
|
|
2023-01-10 22:44:09 +00:00
|
|
|
namespace Shimmie2;
|
|
|
|
|
2019-10-14 18:35:33 +00:00
|
|
|
abstract class ApprovalConfig
|
|
|
|
{
|
2021-12-14 18:32:47 +00:00
|
|
|
public const VERSION = "ext_approval_version";
|
|
|
|
public const IMAGES = "approve_images";
|
|
|
|
public const COMMENTS = "approve_comments";
|
2019-10-14 18:35:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
class Approval extends Extension
|
|
|
|
{
|
2020-01-26 13:19:35 +00:00
|
|
|
/** @var ApprovalTheme */
|
2023-06-27 14:56:49 +00:00
|
|
|
protected Themelet $theme;
|
2020-01-26 13:19:35 +00:00
|
|
|
|
2024-01-15 11:52:35 +00:00
|
|
|
public function onInitExt(InitExtEvent $event): void
|
2019-10-14 18:35:33 +00:00
|
|
|
{
|
|
|
|
global $config;
|
|
|
|
|
|
|
|
$config->set_default_bool(ApprovalConfig::IMAGES, false);
|
|
|
|
$config->set_default_bool(ApprovalConfig::COMMENTS, false);
|
2020-01-30 14:50:30 +00:00
|
|
|
|
2024-01-15 17:32:56 +00:00
|
|
|
Image::$prop_types["approved"] = ImagePropType::BOOL;
|
2024-01-15 18:01:48 +00:00
|
|
|
Image::$prop_types["approved_by_id"] = ImagePropType::INT;
|
2019-10-14 18:35:33 +00:00
|
|
|
}
|
|
|
|
|
2024-01-15 11:52:35 +00:00
|
|
|
public function onImageAddition(ImageAdditionEvent $event): void
|
2023-06-14 08:15:14 +00:00
|
|
|
{
|
2023-06-14 07:48:38 +00:00
|
|
|
global $user, $config;
|
|
|
|
|
2023-06-25 18:33:28 +00:00
|
|
|
if ($config->get_bool(ApprovalConfig::IMAGES) && $user->can(Permissions::BYPASS_IMAGE_APPROVAL)) {
|
2023-06-14 07:48:38 +00:00
|
|
|
self::approve_image($event->image->id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-15 11:52:35 +00:00
|
|
|
public function onPageRequest(PageRequestEvent $event): void
|
2019-10-14 18:35:33 +00:00
|
|
|
{
|
|
|
|
global $page, $user;
|
|
|
|
|
2024-02-11 11:34:09 +00:00
|
|
|
if ($event->page_matches("approve_image/{image_id}", method: "POST", permission: Permissions::APPROVE_IMAGE)) {
|
|
|
|
$image_id = int_escape($event->get_arg('image_id'));
|
2019-10-14 18:35:33 +00:00
|
|
|
self::approve_image($image_id);
|
|
|
|
$page->set_mode(PageMode::REDIRECT);
|
2019-11-02 04:45:28 +00:00
|
|
|
$page->set_redirect(make_link("post/view/" . $image_id));
|
|
|
|
}
|
|
|
|
|
2024-02-11 11:34:09 +00:00
|
|
|
if ($event->page_matches("disapprove_image/{image_id}", method: "POST", permission: Permissions::APPROVE_IMAGE)) {
|
|
|
|
$image_id = int_escape($event->get_arg('image_id'));
|
2019-11-02 04:45:28 +00:00
|
|
|
self::disapprove_image($image_id);
|
|
|
|
$page->set_mode(PageMode::REDIRECT);
|
2019-10-14 18:35:33 +00:00
|
|
|
$page->set_redirect(make_link("post/view/".$image_id));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-15 11:52:35 +00:00
|
|
|
public function onSetupBuilding(SetupBuildingEvent $event): void
|
2019-10-14 19:40:15 +00:00
|
|
|
{
|
2024-02-11 14:51:55 +00:00
|
|
|
$sb = $event->panel->create_new_block("Approval");
|
|
|
|
$sb->add_bool_option(ApprovalConfig::IMAGES, "Posts: ");
|
2019-10-14 19:40:15 +00:00
|
|
|
}
|
|
|
|
|
2024-01-15 11:52:35 +00:00
|
|
|
public function onAdminBuilding(AdminBuildingEvent $event): void
|
2019-10-14 18:35:33 +00:00
|
|
|
{
|
|
|
|
$this->theme->display_admin_form();
|
|
|
|
}
|
|
|
|
|
2024-01-15 11:52:35 +00:00
|
|
|
public function onAdminAction(AdminActionEvent $event): void
|
2019-10-14 18:35:33 +00:00
|
|
|
{
|
|
|
|
global $database, $user;
|
|
|
|
|
|
|
|
$action = $event->action;
|
|
|
|
$event->redirect = true;
|
2023-11-11 21:49:12 +00:00
|
|
|
if ($action === "approval") {
|
2024-02-10 00:00:49 +00:00
|
|
|
$approval_action = $event->params["approval_action"];
|
2019-10-14 18:35:33 +00:00
|
|
|
switch ($approval_action) {
|
|
|
|
case "approve_all":
|
2021-09-22 14:42:41 +00:00
|
|
|
$database->set_timeout(null); // These updates can take a little bit
|
2019-11-02 19:57:34 +00:00
|
|
|
$database->execute(
|
2020-01-30 14:50:30 +00:00
|
|
|
"UPDATE images SET approved = :true, approved_by_id = :approved_by_id WHERE approved = :false",
|
2023-11-11 21:49:12 +00:00
|
|
|
["approved_by_id" => $user->id, "true" => true, "false" => false]
|
2019-10-14 18:35:33 +00:00
|
|
|
);
|
|
|
|
break;
|
2019-11-02 04:45:28 +00:00
|
|
|
case "disapprove_all":
|
2021-09-22 14:42:41 +00:00
|
|
|
$database->set_timeout(null); // These updates can take a little bit
|
2020-01-30 14:50:30 +00:00
|
|
|
$database->execute(
|
|
|
|
"UPDATE images SET approved = :false, approved_by_id = NULL WHERE approved = :true",
|
2023-11-11 21:49:12 +00:00
|
|
|
["true" => true, "false" => false]
|
2020-01-30 14:50:30 +00:00
|
|
|
);
|
2019-10-14 18:35:33 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-15 11:52:35 +00:00
|
|
|
public function onDisplayingImage(DisplayingImageEvent $event): void
|
2019-10-14 18:35:33 +00:00
|
|
|
{
|
2020-06-16 23:40:13 +00:00
|
|
|
global $page;
|
2019-10-14 18:35:33 +00:00
|
|
|
|
2024-02-11 14:51:55 +00:00
|
|
|
if (!$this->check_permissions($event->image)) {
|
2019-10-14 18:35:33 +00:00
|
|
|
$page->set_mode(PageMode::REDIRECT);
|
2023-08-18 11:42:42 +00:00
|
|
|
$page->set_redirect(make_link());
|
2019-10-14 18:35:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-15 11:52:35 +00:00
|
|
|
public function onPageSubNavBuilding(PageSubNavBuildingEvent $event): void
|
2019-10-14 18:35:33 +00:00
|
|
|
{
|
|
|
|
global $user;
|
2023-11-11 21:49:12 +00:00
|
|
|
if ($event->parent == "posts") {
|
2019-11-02 19:57:34 +00:00
|
|
|
if ($user->can(Permissions::APPROVE_IMAGE)) {
|
|
|
|
$event->add_nav_link("posts_unapproved", new Link('/post/list/approved%3Ano/1'), "Pending Approval", null, 60);
|
2019-10-14 18:35:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-15 11:52:35 +00:00
|
|
|
public function onUserBlockBuilding(UserBlockBuildingEvent $event): void
|
2023-03-20 17:17:39 +00:00
|
|
|
{
|
|
|
|
global $user;
|
|
|
|
if ($user->can(Permissions::APPROVE_IMAGE)) {
|
2023-08-18 12:38:55 +00:00
|
|
|
$event->add_link("Pending Approval", search_link(["approved:no"]), 60);
|
2023-03-20 17:17:39 +00:00
|
|
|
}
|
|
|
|
}
|
2019-10-14 18:35:33 +00:00
|
|
|
|
2021-12-14 18:32:47 +00:00
|
|
|
public const SEARCH_REGEXP = "/^approved:(yes|no)/";
|
2024-01-15 11:52:35 +00:00
|
|
|
public function onSearchTermParse(SearchTermParseEvent $event): void
|
2019-10-14 18:35:33 +00:00
|
|
|
{
|
2020-10-29 01:28:46 +00:00
|
|
|
global $user, $config;
|
2019-10-14 18:35:33 +00:00
|
|
|
|
2019-11-02 19:57:34 +00:00
|
|
|
if ($config->get_bool(ApprovalConfig::IMAGES)) {
|
2019-10-14 19:40:15 +00:00
|
|
|
$matches = [];
|
2019-10-14 18:35:33 +00:00
|
|
|
|
2019-10-14 19:40:15 +00:00
|
|
|
if (is_null($event->term) && $this->no_approval_query($event->context)) {
|
2023-11-11 21:49:12 +00:00
|
|
|
$event->add_querylet(new Querylet("approved = :true", ["true" => true]));
|
2019-10-14 19:40:15 +00:00
|
|
|
}
|
2019-10-14 18:35:33 +00:00
|
|
|
|
2020-01-26 16:38:26 +00:00
|
|
|
if (is_null($event->term)) {
|
|
|
|
return;
|
|
|
|
}
|
2019-10-14 19:40:15 +00:00
|
|
|
if (preg_match(self::SEARCH_REGEXP, strtolower($event->term), $matches)) {
|
|
|
|
if ($user->can(Permissions::APPROVE_IMAGE) && $matches[1] == "no") {
|
2023-11-11 21:49:12 +00:00
|
|
|
$event->add_querylet(new Querylet("approved != :true", ["true" => true]));
|
2019-10-14 19:40:15 +00:00
|
|
|
} else {
|
2023-11-11 21:49:12 +00:00
|
|
|
$event->add_querylet(new Querylet("approved = :true", ["true" => true]));
|
2019-10-14 19:40:15 +00:00
|
|
|
}
|
2019-10-14 18:35:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-15 11:52:35 +00:00
|
|
|
public function onHelpPageBuilding(HelpPageBuildingEvent $event): void
|
2019-10-14 18:35:33 +00:00
|
|
|
{
|
2019-10-14 19:46:42 +00:00
|
|
|
global $user, $config;
|
2023-11-11 21:49:12 +00:00
|
|
|
if ($event->key === HelpPages::SEARCH) {
|
2019-10-14 19:46:42 +00:00
|
|
|
if ($user->can(Permissions::APPROVE_IMAGE) && $config->get_bool(ApprovalConfig::IMAGES)) {
|
2023-07-10 18:03:54 +00:00
|
|
|
$event->add_block(new Block("Approval", $this->theme->get_help_html()));
|
2019-10-14 18:35:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-20 14:10:59 +00:00
|
|
|
/**
|
|
|
|
* @param string[] $context
|
|
|
|
*/
|
2019-10-14 18:35:33 +00:00
|
|
|
private function no_approval_query(array $context): bool
|
|
|
|
{
|
|
|
|
foreach ($context as $term) {
|
|
|
|
if (preg_match(self::SEARCH_REGEXP, $term)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2024-01-20 14:10:59 +00:00
|
|
|
public static function approve_image(int $image_id): void
|
2019-10-14 18:35:33 +00:00
|
|
|
{
|
|
|
|
global $database, $user;
|
|
|
|
|
2019-11-02 19:57:34 +00:00
|
|
|
$database->execute(
|
2020-01-30 14:50:30 +00:00
|
|
|
"UPDATE images SET approved = :true, approved_by_id = :approved_by_id WHERE id = :id AND approved = :false",
|
2023-11-11 21:49:12 +00:00
|
|
|
["approved_by_id" => $user->id, "id" => $image_id, "true" => true, "false" => false]
|
2019-10-14 18:35:33 +00:00
|
|
|
);
|
|
|
|
}
|
2019-11-02 04:45:28 +00:00
|
|
|
|
2024-01-20 14:10:59 +00:00
|
|
|
public static function disapprove_image(int $image_id): void
|
2019-11-02 04:45:28 +00:00
|
|
|
{
|
2020-01-26 13:19:35 +00:00
|
|
|
global $database;
|
2019-11-02 04:45:28 +00:00
|
|
|
|
2019-11-02 19:57:34 +00:00
|
|
|
$database->execute(
|
2020-01-30 14:50:30 +00:00
|
|
|
"UPDATE images SET approved = :false, approved_by_id = NULL WHERE id = :id AND approved = :true",
|
2023-11-11 21:49:12 +00:00
|
|
|
["id" => $image_id, "true" => true, "false" => false]
|
2019-11-02 04:45:28 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2020-06-16 23:40:13 +00:00
|
|
|
private function check_permissions(Image $image): bool
|
|
|
|
{
|
|
|
|
global $user, $config;
|
|
|
|
|
2024-01-15 17:12:36 +00:00
|
|
|
if ($config->get_bool(ApprovalConfig::IMAGES) && $image['approved'] === false && !$user->can(Permissions::APPROVE_IMAGE) && $user->id !== $image->owner_id) {
|
2020-06-16 23:40:13 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2024-01-15 11:52:35 +00:00
|
|
|
public function onImageDownloading(ImageDownloadingEvent $event): void
|
2020-06-16 23:40:13 +00:00
|
|
|
{
|
|
|
|
/**
|
|
|
|
* Deny images upon insufficient permissions.
|
|
|
|
**/
|
|
|
|
if (!$this->check_permissions($event->image)) {
|
2024-02-11 15:47:40 +00:00
|
|
|
throw new PermissionDenied("Access denied");
|
2020-06-16 23:40:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-15 11:52:35 +00:00
|
|
|
public function onImageAdminBlockBuilding(ImageAdminBlockBuildingEvent $event): void
|
2019-10-14 18:35:33 +00:00
|
|
|
{
|
2019-10-14 19:40:15 +00:00
|
|
|
global $user, $config;
|
2019-11-02 19:57:34 +00:00
|
|
|
if ($user->can(Permissions::APPROVE_IMAGE) && $config->get_bool(ApprovalConfig::IMAGES)) {
|
2024-02-10 18:35:55 +00:00
|
|
|
if ($event->image['approved'] === true) {
|
|
|
|
$event->add_button("Disapprove", "disapprove_image/".$event->image->id);
|
|
|
|
} else {
|
|
|
|
$event->add_button("Approve", "approve_image/".$event->image->id);
|
|
|
|
}
|
|
|
|
|
2019-10-14 18:35:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-15 11:52:35 +00:00
|
|
|
public function onBulkActionBlockBuilding(BulkActionBlockBuildingEvent $event): void
|
2019-10-14 18:35:33 +00:00
|
|
|
{
|
2019-10-14 19:40:15 +00:00
|
|
|
global $user, $config;
|
2019-10-14 18:35:33 +00:00
|
|
|
|
2023-11-11 21:49:12 +00:00
|
|
|
if ($user->can(Permissions::APPROVE_IMAGE) && $config->get_bool(ApprovalConfig::IMAGES)) {
|
2019-11-02 19:57:34 +00:00
|
|
|
if (in_array("approved:no", $event->search_terms)) {
|
2019-11-02 04:45:28 +00:00
|
|
|
$event->add_action("bulk_approve_image", "Approve", "a");
|
|
|
|
} else {
|
|
|
|
$event->add_action("bulk_disapprove_image", "Disapprove");
|
|
|
|
}
|
2019-10-14 18:35:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-15 11:52:35 +00:00
|
|
|
public function onBulkAction(BulkActionEvent $event): void
|
2019-10-14 18:35:33 +00:00
|
|
|
{
|
2019-12-15 19:47:18 +00:00
|
|
|
global $page, $user;
|
2019-10-14 18:35:33 +00:00
|
|
|
|
|
|
|
switch ($event->action) {
|
|
|
|
case "bulk_approve_image":
|
|
|
|
if ($user->can(Permissions::APPROVE_IMAGE)) {
|
|
|
|
$total = 0;
|
|
|
|
foreach ($event->items as $image) {
|
|
|
|
self::approve_image($image->id);
|
|
|
|
$total++;
|
|
|
|
}
|
2019-12-15 19:47:18 +00:00
|
|
|
$page->flash("Approved $total items");
|
2019-10-14 18:35:33 +00:00
|
|
|
}
|
|
|
|
break;
|
2019-11-02 04:45:28 +00:00
|
|
|
case "bulk_disapprove_image":
|
|
|
|
if ($user->can(Permissions::APPROVE_IMAGE)) {
|
|
|
|
$total = 0;
|
|
|
|
foreach ($event->items as $image) {
|
|
|
|
self::disapprove_image($image->id);
|
|
|
|
$total++;
|
|
|
|
}
|
2019-12-15 19:47:18 +00:00
|
|
|
$page->flash("Disapproved $total items");
|
2019-11-02 04:45:28 +00:00
|
|
|
}
|
|
|
|
break;
|
2019-10-14 18:35:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-15 11:52:35 +00:00
|
|
|
public function onDatabaseUpgrade(DatabaseUpgradeEvent $event): void
|
2019-10-14 18:35:33 +00:00
|
|
|
{
|
2019-11-03 19:04:57 +00:00
|
|
|
global $database;
|
2019-10-14 18:35:33 +00:00
|
|
|
|
2019-11-03 19:04:57 +00:00
|
|
|
if ($this->get_version(ApprovalConfig::VERSION) < 1) {
|
2020-10-26 23:53:33 +00:00
|
|
|
$database->execute("ALTER TABLE images ADD COLUMN approved BOOLEAN NOT NULL DEFAULT FALSE");
|
|
|
|
$database->execute("ALTER TABLE images ADD COLUMN approved_by_id INTEGER NULL");
|
2020-01-30 14:50:30 +00:00
|
|
|
$database->execute("CREATE INDEX images_approved_idx ON images(approved)");
|
2020-10-26 23:53:33 +00:00
|
|
|
$this->set_version(ApprovalConfig::VERSION, 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($this->get_version(ApprovalConfig::VERSION) < 2) {
|
|
|
|
$database->standardise_boolean("images", "approved");
|
|
|
|
$this->set_version(ApprovalConfig::VERSION, 2);
|
2019-10-14 18:35:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|