init
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
<?php declare(strict_types = 1);
|
||||
|
||||
namespace MailPoet\Router\Endpoints;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use MailPoet\Captcha\CaptchaRenderer;
|
||||
use MailPoet\Captcha\PageRenderer;
|
||||
use MailPoet\Config\AccessControl;
|
||||
|
||||
class Captcha {
|
||||
const ENDPOINT = 'captcha';
|
||||
const ACTION_RENDER = 'render';
|
||||
const ACTION_IMAGE = 'image';
|
||||
const ACTION_AUDIO = 'audio';
|
||||
const ACTION_REFRESH = 'refresh';
|
||||
|
||||
private PageRenderer $pageRenderer;
|
||||
private CaptchaRenderer $captchaRenderer;
|
||||
|
||||
public $allowedActions = [
|
||||
self::ACTION_RENDER,
|
||||
self::ACTION_IMAGE,
|
||||
self::ACTION_AUDIO,
|
||||
self::ACTION_REFRESH,
|
||||
];
|
||||
|
||||
public $permissions = [
|
||||
'global' => AccessControl::NO_ACCESS_RESTRICTION,
|
||||
];
|
||||
|
||||
public function __construct(
|
||||
PageRenderer $renderer,
|
||||
CaptchaRenderer $captchaRenderer
|
||||
) {
|
||||
$this->pageRenderer = $renderer;
|
||||
$this->captchaRenderer = $captchaRenderer;
|
||||
}
|
||||
|
||||
public function render($data) {
|
||||
$this->pageRenderer->render($data);
|
||||
}
|
||||
|
||||
public function image($data) {
|
||||
$width = !empty($data['width']) ? (int)$data['width'] : null;
|
||||
$height = !empty($data['height']) ? (int)$data['height'] : null;
|
||||
$sessionId = $data['captcha_session_id'] ?? null;
|
||||
if (!$sessionId) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->captchaRenderer->renderImage($sessionId, $width, $height);
|
||||
exit;
|
||||
}
|
||||
|
||||
public function audio($data) {
|
||||
$sessionId = $data['captcha_session_id'] ?? null;
|
||||
if (!$sessionId) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->captchaRenderer->renderAudio($sessionId);
|
||||
exit;
|
||||
}
|
||||
|
||||
public function refresh($data) {
|
||||
$sessionId = $data['captcha_session_id'] ?? null;
|
||||
if (!$sessionId) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->captchaRenderer->refreshPhrase($sessionId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
|
||||
|
||||
namespace MailPoet\Router\Endpoints;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use MailPoet\Config\AccessControl;
|
||||
use MailPoet\Cron\CronHelper;
|
||||
use MailPoet\Cron\DaemonHttpRunner;
|
||||
|
||||
class CronDaemon {
|
||||
const ENDPOINT = 'cron_daemon';
|
||||
const ACTION_RUN = 'run';
|
||||
const ACTION_PING = 'ping';
|
||||
const ACTION_PING_RESPONSE = 'pingResponse';
|
||||
public $allowedActions = [
|
||||
self::ACTION_RUN,
|
||||
self::ACTION_PING,
|
||||
self::ACTION_PING_RESPONSE,
|
||||
];
|
||||
public $data;
|
||||
public $permissions = [
|
||||
'global' => AccessControl::NO_ACCESS_RESTRICTION,
|
||||
];
|
||||
|
||||
/** @var DaemonHttpRunner */
|
||||
private $daemonRunner;
|
||||
|
||||
/** @var CronHelper */
|
||||
private $cronHelper;
|
||||
|
||||
public function __construct(
|
||||
DaemonHttpRunner $daemonRunner,
|
||||
CronHelper $cronHelper
|
||||
) {
|
||||
$this->daemonRunner = $daemonRunner;
|
||||
$this->cronHelper = $cronHelper;
|
||||
}
|
||||
|
||||
public function run($data) {
|
||||
$this->daemonRunner->run($data);
|
||||
}
|
||||
|
||||
public function ping() {
|
||||
die(esc_html($this->cronHelper->pingDaemon()));
|
||||
}
|
||||
|
||||
public function pingResponse() {
|
||||
$this->daemonRunner->ping();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
|
||||
|
||||
namespace MailPoet\Router\Endpoints;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use MailPoet\Config\AccessControl;
|
||||
use MailPoet\Form\PreviewPage;
|
||||
use MailPoet\WP\Functions as WPFunctions;
|
||||
|
||||
class FormPreview {
|
||||
const ENDPOINT = 'form_preview';
|
||||
const ACTION_VIEW = 'view';
|
||||
|
||||
/** @var WPFunctions */
|
||||
private $wp;
|
||||
|
||||
/** @var array|null */
|
||||
private $data;
|
||||
|
||||
/** @var PreviewPage */
|
||||
private $formPreviewPage;
|
||||
|
||||
public $allowedActions = [self::ACTION_VIEW];
|
||||
public $permissions = [
|
||||
'global' => AccessControl::NO_ACCESS_RESTRICTION,
|
||||
];
|
||||
|
||||
public function __construct(
|
||||
WPFunctions $wp,
|
||||
PreviewPage $formPreviewPage
|
||||
) {
|
||||
$this->wp = $wp;
|
||||
$this->formPreviewPage = $formPreviewPage;
|
||||
}
|
||||
|
||||
public function view(array $data) {
|
||||
$this->data = $data;
|
||||
$this->wp->addFilter('the_content', [$this, 'renderContent'], 10);
|
||||
$this->wp->addFilter('the_title', [$this->formPreviewPage, 'renderTitle'], 10, 2);
|
||||
$this->wp->addFilter('show_admin_bar', function () {
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
public function renderContent(): string {
|
||||
if (!array_key_exists('id', $this->data ?? []) || !isset($this->data['form_type'])) {
|
||||
return '';
|
||||
}
|
||||
return $this->formPreviewPage->renderPage(
|
||||
(int)$this->data['id'],
|
||||
(string)$this->data['form_type'],
|
||||
(string)$this->data['editor_url']
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
|
||||
|
||||
namespace MailPoet\Router\Endpoints;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use MailPoet\Config\AccessControl;
|
||||
use MailPoet\Entities\StatisticsUnsubscribeEntity;
|
||||
use MailPoet\Subscription as UserSubscription;
|
||||
use MailPoet\Util\Request;
|
||||
use MailPoet\WP\Functions as WPFunctions;
|
||||
|
||||
class Subscription {
|
||||
const ENDPOINT = 'subscription';
|
||||
const ACTION_CONFIRM = 'confirm';
|
||||
const ACTION_MANAGE = 'manage';
|
||||
const ACTION_UNSUBSCRIBE = 'unsubscribe';
|
||||
const ACTION_CONFIRM_UNSUBSCRIBE = 'confirmUnsubscribe';
|
||||
const ACTION_RE_ENGAGEMENT = 'reEngagement';
|
||||
|
||||
public $allowedActions = [
|
||||
self::ACTION_CONFIRM,
|
||||
self::ACTION_MANAGE,
|
||||
self::ACTION_UNSUBSCRIBE,
|
||||
self::ACTION_CONFIRM_UNSUBSCRIBE,
|
||||
self::ACTION_RE_ENGAGEMENT,
|
||||
];
|
||||
|
||||
public $permissions = [
|
||||
'global' => AccessControl::NO_ACCESS_RESTRICTION,
|
||||
];
|
||||
|
||||
/** @var UserSubscription\Pages */
|
||||
private $subscriptionPages;
|
||||
|
||||
/** @var WPFunctions */
|
||||
private $wp;
|
||||
|
||||
/*** @var Request */
|
||||
private $request;
|
||||
|
||||
public function __construct(
|
||||
UserSubscription\Pages $subscriptionPages,
|
||||
WPFunctions $wp,
|
||||
Request $request
|
||||
) {
|
||||
$this->subscriptionPages = $subscriptionPages;
|
||||
$this->wp = $wp;
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
public function confirm($data) {
|
||||
$subscription = $this->initSubscriptionPage(UserSubscription\Pages::ACTION_CONFIRM, $data);
|
||||
$subscription->confirm();
|
||||
}
|
||||
|
||||
public function confirmUnsubscribe($data) {
|
||||
$enableUnsubscribeConfirmation = $this->wp->applyFilters('mailpoet_unsubscribe_confirmation_enabled', true);
|
||||
if ($this->request->isPost()) {
|
||||
$this->applyOneClickUnsubscribeStrategy($data);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($enableUnsubscribeConfirmation) {
|
||||
$this->initSubscriptionPage(UserSubscription\Pages::ACTION_CONFIRM_UNSUBSCRIBE, $data);
|
||||
} else {
|
||||
$this->unsubscribe($data);
|
||||
}
|
||||
}
|
||||
|
||||
public function manage($data) {
|
||||
$this->initSubscriptionPage(UserSubscription\Pages::ACTION_MANAGE, $data);
|
||||
}
|
||||
|
||||
public function unsubscribe($data) {
|
||||
if ($this->request->isPost()) {
|
||||
$this->applyOneClickUnsubscribeStrategy($data);
|
||||
exit;
|
||||
} else {
|
||||
$subscription = $this->initSubscriptionPage(UserSubscription\Pages::ACTION_UNSUBSCRIBE, $data);
|
||||
$subscription->unsubscribe(StatisticsUnsubscribeEntity::METHOD_LINK);
|
||||
}
|
||||
}
|
||||
|
||||
public function reEngagement($data) {
|
||||
$this->initSubscriptionPage(UserSubscription\Pages::ACTION_RE_ENGAGEMENT, $data);
|
||||
}
|
||||
|
||||
private function initSubscriptionPage($action, $data) {
|
||||
return $this->subscriptionPages->init($action, $data, true, true);
|
||||
}
|
||||
|
||||
private function applyOneClickUnsubscribeStrategy($data): void {
|
||||
$subscription = $this->initSubscriptionPage(UserSubscription\Pages::ACTION_UNSUBSCRIBE, $data);
|
||||
$subscription->unsubscribe(StatisticsUnsubscribeEntity::METHOD_ONE_CLICK);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
|
||||
|
||||
namespace MailPoet\Router\Endpoints;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use MailPoet\Config\AccessControl;
|
||||
use MailPoet\NewsletterTemplates\TemplateImageLoader;
|
||||
|
||||
class TemplateImage {
|
||||
const ENDPOINT = 'template_image';
|
||||
const ACTION_GET_EXTERNAL_IMAGE = 'getExternalImage';
|
||||
|
||||
/** @var TemplateImageLoader */
|
||||
private $templateImageLoader;
|
||||
|
||||
public $allowedActions = [self::ACTION_GET_EXTERNAL_IMAGE];
|
||||
public $permissions = [
|
||||
'global' => AccessControl::PERMISSION_MANAGE_EMAILS,
|
||||
];
|
||||
|
||||
public function __construct(
|
||||
TemplateImageLoader $templateImageLoader
|
||||
) {
|
||||
$this->templateImageLoader = $templateImageLoader;
|
||||
}
|
||||
|
||||
public function getExternalImage($data = [], $return = false) {
|
||||
if (empty($_GET['url'])) {
|
||||
return false;
|
||||
}
|
||||
$result = $this->templateImageLoader->loadExternalImage(
|
||||
sanitize_text_field(wp_unslash($_GET['url']))
|
||||
);
|
||||
if ($return) {
|
||||
return $result;
|
||||
}
|
||||
exit;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
|
||||
|
||||
namespace MailPoet\Router\Endpoints;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use MailPoet\Config\AccessControl;
|
||||
use MailPoet\Cron\Workers\StatsNotifications\NewsletterLinkRepository;
|
||||
use MailPoet\Entities\SendingQueueEntity;
|
||||
use MailPoet\Newsletter\Links\Links;
|
||||
use MailPoet\Newsletter\NewslettersRepository;
|
||||
use MailPoet\Newsletter\Sending\SendingQueuesRepository;
|
||||
use MailPoet\Statistics\Track\Clicks;
|
||||
use MailPoet\Statistics\Track\Opens;
|
||||
use MailPoet\Subscribers\LinkTokens;
|
||||
use MailPoet\Subscribers\SubscribersRepository;
|
||||
use MailPoet\WP\Functions as WPFunctions;
|
||||
|
||||
class Track {
|
||||
const ENDPOINT = 'track';
|
||||
const ACTION_CLICK = 'click';
|
||||
const ACTION_OPEN = 'open';
|
||||
public $allowedActions = [
|
||||
self::ACTION_CLICK,
|
||||
self::ACTION_OPEN,
|
||||
];
|
||||
public $permissions = [
|
||||
'global' => AccessControl::NO_ACCESS_RESTRICTION,
|
||||
];
|
||||
|
||||
/** @var Clicks */
|
||||
private $clicks;
|
||||
|
||||
/** @var Opens */
|
||||
private $opens;
|
||||
|
||||
/** @var LinkTokens */
|
||||
private $linkTokens;
|
||||
|
||||
/** @var SendingQueuesRepository */
|
||||
private $sendingQueuesRepository;
|
||||
|
||||
/** @var SubscribersRepository */
|
||||
private $subscribersRepository;
|
||||
|
||||
/** @var NewslettersRepository */
|
||||
private $newslettersRepository;
|
||||
|
||||
/** @var NewsletterLinkRepository */
|
||||
private $newsletterLinkRepository;
|
||||
|
||||
/** @var Links */
|
||||
private $links;
|
||||
|
||||
public function __construct(
|
||||
Clicks $clicks,
|
||||
Opens $opens,
|
||||
SendingQueuesRepository $sendingQueuesRepository,
|
||||
SubscribersRepository $subscribersRepository,
|
||||
NewslettersRepository $newslettersRepository,
|
||||
NewsletterLinkRepository $newsletterLinkRepository,
|
||||
LinkTokens $linkTokens,
|
||||
Links $links
|
||||
) {
|
||||
$this->clicks = $clicks;
|
||||
$this->opens = $opens;
|
||||
$this->linkTokens = $linkTokens;
|
||||
$this->sendingQueuesRepository = $sendingQueuesRepository;
|
||||
$this->subscribersRepository = $subscribersRepository;
|
||||
$this->newslettersRepository = $newslettersRepository;
|
||||
$this->newsletterLinkRepository = $newsletterLinkRepository;
|
||||
$this->links = $links;
|
||||
}
|
||||
|
||||
public function click($data) {
|
||||
return $this->clicks->track($this->_processTrackData($data));
|
||||
}
|
||||
|
||||
public function open($data) {
|
||||
return $this->opens->track($this->_processTrackData($data));
|
||||
}
|
||||
|
||||
public function _processTrackData($data) {
|
||||
$data = (object)$this->links->transformUrlDataObject($data);
|
||||
if (
|
||||
empty($data->queue_id) || // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
|
||||
empty($data->subscriber_id) || // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
|
||||
empty($data->subscriber_token) // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
$data->queue = $this->sendingQueuesRepository->findOneById($data->queue_id);// phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
|
||||
$data->subscriber = $this->subscribersRepository->findOneById($data->subscriber_id); // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
|
||||
$data->newsletter = (isset($data->newsletter_id)) ? $this->newslettersRepository->findOneById($data->newsletter_id) : null; // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
|
||||
if (!$data->newsletter && ($data->queue instanceof SendingQueueEntity)) {
|
||||
$data->newsletter = $data->queue->getNewsletter();
|
||||
}
|
||||
if (!empty($data->link_hash)) { // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
|
||||
$data->link = $this->newsletterLinkRepository->findOneBy([
|
||||
'hash' => $data->link_hash, // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
|
||||
'queue' => $data->queue_id, // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
|
||||
]);
|
||||
}
|
||||
$data->userAgent = isset($_SERVER['HTTP_USER_AGENT']) ? sanitize_text_field(wp_unslash($_SERVER['HTTP_USER_AGENT'])) : null;
|
||||
return $this->_validateTrackData($data);
|
||||
}
|
||||
|
||||
public function _validateTrackData($data) {
|
||||
if (!$data->subscriber || !$data->queue || !$data->newsletter) return false;
|
||||
$subscriberTokenMatch = $this->linkTokens->verifyToken($data->subscriber, $data->subscriber_token); // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
|
||||
if (!$subscriberTokenMatch) {
|
||||
$this->terminate(403);
|
||||
}
|
||||
// return if this is a WP user previewing the newsletter
|
||||
if ($data->subscriber->isWPUser() && $data->preview) {
|
||||
return $data;
|
||||
}
|
||||
// check if the newsletter was sent to the subscriber
|
||||
return ($this->sendingQueuesRepository->isSubscriberProcessed($data->queue, $data->subscriber)) ?
|
||||
$data :
|
||||
false;
|
||||
}
|
||||
|
||||
public function terminate($code) {
|
||||
WPFunctions::get()->statusHeader($code);
|
||||
WPFunctions::get()->getTemplatePart((string)$code);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php // phpcs:ignore SlevomatCodingStandard.TypeHints.DeclareStrictTypes.DeclareStrictTypesMissing
|
||||
|
||||
namespace MailPoet\Router\Endpoints;
|
||||
|
||||
if (!defined('ABSPATH')) exit;
|
||||
|
||||
|
||||
use MailPoet\Config\AccessControl;
|
||||
use MailPoet\Newsletter\ViewInBrowser\ViewInBrowserController;
|
||||
use MailPoet\WP\Functions as WPFunctions;
|
||||
|
||||
class ViewInBrowser {
|
||||
const ENDPOINT = 'view_in_browser';
|
||||
const ACTION_VIEW = 'view';
|
||||
|
||||
public $allowedActions = [self::ACTION_VIEW];
|
||||
public $permissions = [
|
||||
'global' => AccessControl::NO_ACCESS_RESTRICTION,
|
||||
];
|
||||
|
||||
/** @var ViewInBrowserController */
|
||||
private $viewInBrowserController;
|
||||
|
||||
public function __construct(
|
||||
ViewInBrowserController $viewInBrowserController
|
||||
) {
|
||||
$this->viewInBrowserController = $viewInBrowserController;
|
||||
}
|
||||
|
||||
public function view(array $data) {
|
||||
try {
|
||||
$viewData = $this->viewInBrowserController->view($data);
|
||||
$this->displayNewsletter($viewData);
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
$this->abort();
|
||||
}
|
||||
}
|
||||
|
||||
private function displayNewsletter($result) {
|
||||
if ($result) {
|
||||
header('Content-Type: text/html; charset=utf-8');
|
||||
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
echo $result;
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
private function abort() {
|
||||
global $wp_query;// phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
|
||||
WPFunctions::get()->statusHeader(404);
|
||||
$wp_query->set_404();// phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
|
||||
exit;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<?php
|
||||
Reference in New Issue
Block a user