| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315 |
- <?php
- namespace MailPoet\API\JSON\v1;
- if (!defined('ABSPATH')) exit;
- use Exception;
- use InvalidArgumentException;
- use MailPoet\API\JSON\Endpoint as APIEndpoint;
- use MailPoet\API\JSON\Error as APIError;
- use MailPoet\API\JSON\Response;
- use MailPoet\API\JSON\ResponseBuilders\SegmentsResponseBuilder;
- use MailPoet\Config\AccessControl;
- use MailPoet\Cron\CronWorkerScheduler;
- use MailPoet\Cron\Workers\WooCommerceSync;
- use MailPoet\Doctrine\Validator\ValidationException;
- use MailPoet\Entities\SegmentEntity;
- use MailPoet\Entities\SubscriberEntity;
- use MailPoet\Form\FormsRepository;
- use MailPoet\Listing;
- use MailPoet\Newsletter\Segment\NewsletterSegmentRepository;
- use MailPoet\Segments\SegmentListingRepository;
- use MailPoet\Segments\SegmentSaveController;
- use MailPoet\Segments\SegmentsRepository;
- use MailPoet\Segments\WooCommerce;
- use MailPoet\Segments\WP;
- use MailPoet\Subscribers\SubscribersRepository;
- use MailPoet\UnexpectedValueException;
- use MailPoet\WP\Functions as WPFunctions;
- class Segments extends APIEndpoint {
- public $permissions = [
- 'global' => AccessControl::PERMISSION_MANAGE_SEGMENTS,
- ];
- /** @var Listing\Handler */
- private $listingHandler;
- /** @var SegmentsRepository */
- private $segmentsRepository;
- /** @var SegmentsResponseBuilder */
- private $segmentsResponseBuilder;
- /** @var SegmentSaveController */
- private $segmentSavecontroller;
- /** @var SubscribersRepository */
- private $subscribersRepository;
- /** @var WooCommerce */
- private $wooCommerceSync;
- /** @var WP */
- private $wpSegment;
- /** @var SegmentListingRepository */
- private $segmentListingRepository;
- /** @var NewsletterSegmentRepository */
- private $newsletterSegmentRepository;
- /** @var CronWorkerScheduler */
- private $cronWorkerScheduler;
- /** @var FormsRepository */
- private $formsRepository;
- public function __construct(
- Listing\Handler $listingHandler,
- SegmentsRepository $segmentsRepository,
- SegmentListingRepository $segmentListingRepository,
- SegmentsResponseBuilder $segmentsResponseBuilder,
- SegmentSaveController $segmentSavecontroller,
- SubscribersRepository $subscribersRepository,
- WooCommerce $wooCommerce,
- WP $wpSegment,
- NewsletterSegmentRepository $newsletterSegmentRepository,
- CronWorkerScheduler $cronWorkerScheduler,
- FormsRepository $formsRepository
- ) {
- $this->listingHandler = $listingHandler;
- $this->wooCommerceSync = $wooCommerce;
- $this->segmentsRepository = $segmentsRepository;
- $this->segmentsResponseBuilder = $segmentsResponseBuilder;
- $this->segmentSavecontroller = $segmentSavecontroller;
- $this->subscribersRepository = $subscribersRepository;
- $this->wpSegment = $wpSegment;
- $this->segmentListingRepository = $segmentListingRepository;
- $this->newsletterSegmentRepository = $newsletterSegmentRepository;
- $this->cronWorkerScheduler = $cronWorkerScheduler;
- $this->formsRepository = $formsRepository;
- }
- public function get($data = []) {
- $id = (isset($data['id']) ? (int)$data['id'] : false);
- $segment = $this->segmentsRepository->findOneById($id);
- if ($segment instanceof SegmentEntity) {
- return $this->successResponse($this->segmentsResponseBuilder->build($segment));
- } else {
- return $this->errorResponse([
- APIError::NOT_FOUND => WPFunctions::get()->__('This list does not exist.', 'mailpoet'),
- ]);
- }
- }
- public function listing($data = []) {
- $data['params'] = $data['params'] ?? ['lists']; // Dummy param to apply constraints properly
- $definition = $this->listingHandler->getListingDefinition($data);
- $items = $this->segmentListingRepository->getData($definition);
- $count = $this->segmentListingRepository->getCount($definition);
- $filters = $this->segmentListingRepository->getFilters($definition);
- $groups = $this->segmentListingRepository->getGroups($definition);
- $segments = $this->segmentsResponseBuilder->buildForListing($items);
- return $this->successResponse($segments, [
- 'count' => $count,
- 'filters' => $filters,
- 'groups' => $groups,
- ]);
- }
- public function save($data = []) {
- try {
- $segment = $this->segmentSavecontroller->save($data);
- } catch (ValidationException $exception) {
- return $this->badRequest([
- APIError::BAD_REQUEST => __('Please specify a name.', 'mailpoet'),
- ]);
- } catch (InvalidArgumentException $exception) {
- return $this->badRequest([
- APIError::BAD_REQUEST => __('Another record already exists. Please specify a different "name".', 'mailpoet'),
- ]);
- }
- $response = $this->segmentsResponseBuilder->build($segment);
- return $this->successResponse($response);
- }
- public function restore($data = []) {
- $segment = $this->getSegment($data);
- if ($segment instanceof SegmentEntity) {
- if (!$this->isTrashOrRestoreAllowed($segment)) {
- return $this->errorResponse([
- APIError::FORBIDDEN => WPFunctions::get()->__('This list cannot be moved to trash.', 'mailpoet'),
- ]);
- }
- // When the segment is of type WP_USERS we want to restore all its subscribers
- if ($segment->getType() === SegmentEntity::TYPE_WP_USERS) {
- $subscribers = $this->subscribersRepository->findBySegment((int)$segment->getId());
- $subscriberIds = array_map(function (SubscriberEntity $subscriberEntity): int {
- return (int)$subscriberEntity->getId();
- }, $subscribers);
- $this->subscribersRepository->bulkRestore($subscriberIds);
- }
- $this->segmentsRepository->bulkRestore([$segment->getId()], $segment->getType());
- $this->segmentsRepository->refresh($segment);
- return $this->successResponse(
- $this->segmentsResponseBuilder->build($segment),
- ['count' => 1]
- );
- } else {
- return $this->errorResponse([
- APIError::NOT_FOUND => WPFunctions::get()->__('This list does not exist.', 'mailpoet'),
- ]);
- }
- }
- public function trash($data = []) {
- $segment = $this->getSegment($data);
- if (!$segment instanceof SegmentEntity) {
- return $this->errorResponse([
- APIError::NOT_FOUND => WPFunctions::get()->__('This list does not exist.', 'mailpoet'),
- ]);
- }
- if (!$this->isTrashOrRestoreAllowed($segment)) {
- return $this->errorResponse([
- APIError::FORBIDDEN => WPFunctions::get()->__('This list cannot be moved to trash.', 'mailpoet'),
- ]);
- }
- $activelyUsedNewslettersSubjects = $this->newsletterSegmentRepository->getSubjectsOfActivelyUsedEmailsForSegments([$segment->getId()]);
- if (isset($activelyUsedNewslettersSubjects[$segment->getId()])) {
- return $this->badRequest([
- APIError::BAD_REQUEST => str_replace(
- '%$1s',
- "'" . join("', '", $activelyUsedNewslettersSubjects[$segment->getId()] ) . "'",
- _x('List cannot be deleted because it’s used for %$1s email', 'Alert shown when trying to delete segment, which is assigned to any automatic emails.', 'mailpoet')
- ),
- ]);
- }
- $activelyUsedFormNames = $this->formsRepository->getNamesOfFormsForSegments();
- if (isset($activelyUsedFormNames[$segment->getId()])) {
- return $this->badRequest([
- APIError::BAD_REQUEST => str_replace(
- '%$1s',
- "'" . join("', '", $activelyUsedFormNames[$segment->getId()] ) . "'",
- _nx(
- 'List cannot be deleted because it’s used for %$1s form',
- 'List cannot be deleted because it’s used for %$1s forms',
- count($activelyUsedFormNames[$segment->getId()]),
- 'Alert shown when trying to delete segment, when it is assigned to a form.',
- 'mailpoet'
- )
- ),
- ]);
- }
- // When the segment is of type WP_USERS we want to trash all subscribers who aren't subscribed in another list
- if ($segment->getType() === SegmentEntity::TYPE_WP_USERS) {
- $subscribers = $this->subscribersRepository->findExclusiveSubscribersBySegment((int)$segment->getId());
- $subscriberIds = array_map(function (SubscriberEntity $subscriberEntity): int {
- return (int)$subscriberEntity->getId();
- }, $subscribers);
- $this->subscribersRepository->bulkTrash($subscriberIds);
- }
- $this->segmentsRepository->doTrash([$segment->getId()], $segment->getType());
- $this->segmentsRepository->refresh($segment);
- return $this->successResponse(
- $this->segmentsResponseBuilder->build($segment),
- ['count' => 1]
- );
- }
- public function delete($data = []) {
- $segment = $this->getSegment($data);
- if ($segment instanceof SegmentEntity) {
- $this->segmentsRepository->bulkDelete([$segment->getId()]);
- return $this->successResponse(null, ['count' => 1]);
- } else {
- return $this->errorResponse([
- APIError::NOT_FOUND => WPFunctions::get()->__('This list does not exist.', 'mailpoet'),
- ]);
- }
- }
- public function duplicate($data = []) {
- $segment = $this->getSegment($data);
- if ($segment instanceof SegmentEntity) {
- try {
- $duplicate = $this->segmentSavecontroller->duplicate($segment);
- } catch (Exception $e) {
- return $this->errorResponse([
- APIError::UNKNOWN => __('Duplicating of segment failed.', 'mailpoet'),
- ], [], Response::STATUS_UNKNOWN);
- }
- return $this->successResponse(
- $this->segmentsResponseBuilder->build($duplicate),
- ['count' => 1]
- );
- } else {
- return $this->errorResponse([
- APIError::NOT_FOUND => WPFunctions::get()->__('This list does not exist.', 'mailpoet'),
- ]);
- }
- }
- public function synchronize($data) {
- try {
- if ($data['type'] === SegmentEntity::TYPE_WC_USERS) {
- $this->cronWorkerScheduler->scheduleImmediatelyIfNotRunning(WooCommerceSync::TASK_TYPE);
- } else {
- $this->wpSegment->synchronizeUsers();
- }
- } catch (\Exception $e) {
- return $this->errorResponse([
- $e->getCode() => $e->getMessage(),
- ]);
- }
- return $this->successResponse(null);
- }
- public function bulkAction($data = []) {
- $definition = $this->listingHandler->getListingDefinition($data['listing']);
- $ids = $this->segmentListingRepository->getActionableIds($definition);
- $count = 0;
- if ($data['action'] === 'trash') {
- $count = $this->segmentsRepository->bulkTrash($ids);
- } elseif ($data['action'] === 'restore') {
- $count = $this->segmentsRepository->bulkRestore($ids);
- } elseif ($data['action'] === 'delete') {
- $count = $this->segmentsRepository->bulkDelete($ids);
- } else {
- throw UnexpectedValueException::create()
- ->withErrors([APIError::BAD_REQUEST => "Invalid bulk action '{$data['action']}' provided."]);
- }
- return $this->successResponse(null, ['count' => $count]);
- }
- private function isTrashOrRestoreAllowed(SegmentEntity $segment): bool {
- $allowedSegmentTypes = [
- SegmentEntity::TYPE_DEFAULT,
- SegmentEntity::TYPE_WP_USERS,
- ];
- if (in_array($segment->getType(), $allowedSegmentTypes, true)) {
- return true;
- }
- return false;
- }
- private function getSegment(array $data): ?SegmentEntity {
- return isset($data['id'])
- ? $this->segmentsRepository->findOneById((int)$data['id'])
- : null;
- }
- }
|