<?php declare(strict_types = 1);
namespace MailPoet\Newsletter;
if (!defined('ABSPATH')) exit;
use MailPoet\Listing\ListingDefinition;
use MailPoet\Newsletter\Listing\NewsletterListingRepository;
use MailPoet\Newsletter\NewslettersRepository;
use MailPoet\WP\Functions as WPFunctions;
/**
* Centralized newsletter bulk-action dispatcher used by the REST endpoint at
* `mailpoet/v1/newsletters/bulk-action`. The `export_stats` action is handled
* by the REST endpoint directly because it is asynchronous and premium-gated;
* this controller covers the synchronous destructive actions.
*/
class BulkActionController {
public const ACTION_TRASH = 'trash';
public const ACTION_RESTORE = 'restore';
public const ACTION_DELETE = 'delete';
public const SUPPORTED_ACTIONS = [
self::ACTION_TRASH,
self::ACTION_RESTORE,
self::ACTION_DELETE,
];
/** @var NewsletterListingRepository */
private $newsletterListingRepository;
/** @var NewslettersRepository */
private $newslettersRepository;
/** @var NewsletterDeleteController */
private $newsletterDeleteController;
/** @var WPFunctions */
private $wp;
public function __construct(
NewsletterListingRepository $newsletterListingRepository,
NewslettersRepository $newslettersRepository,
NewsletterDeleteController $newsletterDeleteController,
WPFunctions $wp
) {
$this->newsletterListingRepository = $newsletterListingRepository;
$this->newslettersRepository = $newslettersRepository;
$this->newsletterDeleteController = $newsletterDeleteController;
$this->wp = $wp;
}
/**
* @return array{action: string, count: int, ids: int[]}
* @throws BulkActionException
*/
public function execute(string $action, ListingDefinition $definition): array {
if (!in_array($action, self::SUPPORTED_ACTIONS, true)) {
throw new BulkActionException(
// translators: %s is the offending bulk-action name.
sprintf(__("Invalid bulk action '%s' provided.", 'mailpoet'), $action),
'mailpoet_newsletters_invalid_bulk_action',
400
);
}
$ids = array_values(array_map('intval', $this->newsletterListingRepository->getActionableIds($definition)));
if ($action === self::ACTION_TRASH) {
$this->newslettersRepository->bulkTrash($ids);
} elseif ($action === self::ACTION_RESTORE) {
$this->newslettersRepository->bulkRestore($ids);
} elseif ($action === self::ACTION_DELETE) {
// Hooks fire around the cascading delete so premium add-ons (and any
// third-party listeners) keep observing the same lifecycle they did
// under the legacy JSON endpoint.
$this->wp->doAction('mailpoet_api_newsletters_delete_before', $ids);
$this->newsletterDeleteController->bulkDelete($ids);
$this->wp->doAction('mailpoet_api_newsletters_delete_after', $ids);
}
return [
'action' => $action,
'count' => count($ids),
'ids' => $ids,
];
}
}