Skip to content

Commit

Permalink
TASK: refactor sending and generation code to be async
Browse files Browse the repository at this point in the history
  • Loading branch information
dimaip committed Jan 27, 2017
1 parent 7f14ee5 commit 74e7f95
Show file tree
Hide file tree
Showing 7 changed files with 123 additions and 108 deletions.
92 changes: 18 additions & 74 deletions Classes/Psmb/Newsletter/Command/NewsletterCommandController.php
Original file line number Diff line number Diff line change
@@ -1,19 +1,11 @@
<?php
namespace Psmb\Newsletter\Command;

use TYPO3\Flow\Annotations as Flow;
use Psmb\Newsletter\Domain\Model\Subscriber;
use Psmb\Newsletter\Domain\Repository\SubscriberRepository;
use Psmb\Newsletter\Service\FusionMailService;
use TYPO3\Flow\Annotations as Flow;
use TYPO3\Flow\Cli\CommandController;
use TYPO3\Flow\Http\Request;
use TYPO3\Flow\Http\Response;
use TYPO3\Flow\Http\Uri;
use TYPO3\Flow\Mvc\ActionRequest;
use TYPO3\Flow\Mvc\Routing\UriBuilder;
use TYPO3\Flow\Mvc\Controller\Arguments;
use TYPO3\Flow\Mvc\Controller\ControllerContext;
use TYPO3\Flow\Persistence\PersistenceManagerInterface;

/**
* @Flow\Scope("singleton")
Expand Down Expand Up @@ -44,22 +36,12 @@ class NewsletterCommandController extends CommandController
*/
protected $subscriptions;

/**
* We can't do this in constructor as we need configuration to be injected
*/
public function initializeObject() {
$request = $this->createRequest();
$request->setFormat('html');
$controllerContext = $this->createControllerContext($request);
$this->fusionMailService->setupObject($controllerContext, $request);
}

/**
* Import newsletter subscribers from CSV.
* CSV should be in the format `"[email protected]","User Name","subscriptionId1|sibscriptionId2"`
* CSV should be in the format `"[email protected]","User Name","subscriptionId1|subscriptionId2"`
*
* @param string $filename
* @return string
* @return void
*/
public function importCsvCommand($filename)
{
Expand Down Expand Up @@ -96,7 +78,7 @@ public function importCsvCommand($filename)
* @param string $subscription Subscription id to send newsletter to
* @param string $interval Alternatively select all subscriptions with the given interval (useful for cron jobs)
* @param bool $dryRun DryRun: generate messages but don't send
* @return string
* @return void
*/
public function sendCommand($subscription = null, $interval = null, $dryRun = null)
{
Expand All @@ -115,72 +97,34 @@ public function sendCommand($subscription = null, $interval = null, $dryRun = nu
$this->sendAndExit(1);
}

$nestedLetters = array_map([$this, 'generateLettersForSubscription'], $subscriptions);
$letters = array_reduce($nestedLetters, function ($acc, $item) {
return array_merge($acc, $item);
}, []);

if ($dryRun) {
$this->outputLine(print_r($letters, 1));
} else {
array_map(function($letter) {
$this->fusionMailService->sendLetter($letter);
}, $letters);
}
array_walk($subscriptions, function ($subscription) use ($dryRun) {
$this->sendLettersForSubscription($subscription, $dryRun);
});
}

/**
* Generate a letter for each subscriber in the subscription
*
* @param array $subscription
* @return array Array of letters
* @param bool $dryRun
* @return void
*/
protected function generateLettersForSubscription($subscription)
protected function sendLettersForSubscription($subscription, $dryRun)
{
$subscribers = $this->subscriberRepository->findBySubscriptionId($subscription['identifier'])->toArray();

$this->outputLine('Sending letters for subscription %s (%s subscribers)', [$subscription['identifier'], count($subscribers)]);
$this->outputLine('-------------------------------------------------------------------------------');
$letters = array_map(function ($subscriber) use ($subscription) {

array_walk($subscribers, function ($subscriber) use ($subscription, $dryRun) {
$this->outputLine('Sending a letter for %s', [$subscriber->getEmail()]);
$letter = $this->fusionMailService->generateSubscriptionLetter($subscriber, $subscription);
if (!$letter) {
$this->outputLine('<error>Nothing to send</error>');
if ($dryRun) {
$letter = $this->fusionMailService->generateSubscriptionLetter($subscriber, $subscription);
$this->outputLine(print_r($letter, true));
} else {
$this->fusionMailService->generateSubscriptionLetterAndSend($subscriber, $subscription);
}
return $letter;
}, $subscribers);
return array_filter($letters);
});
}

/**
* @return ActionRequest
*/
protected function createRequest() {
$_SERVER['FLOW_REWRITEURLS'] = 1;
$httpRequest = Request::createFromEnvironment();
if ($this->baseUri) {
$baseUri = new Uri($this->baseUri);
$httpRequest->setBaseUri($baseUri);
}
return new ActionRequest($httpRequest);
}

/**
* Creates a controller content context for live dimension
*
* @param ActionRequest $request
* @return ControllerContext
*/
protected function createControllerContext($request)
{
$uriBuilder = new UriBuilder();
$uriBuilder->setRequest($request);
$controllerContext = new ControllerContext(
$request,
new Response(),
new Arguments([]),
$uriBuilder
);
return $controllerContext;
}
}
37 changes: 16 additions & 21 deletions Classes/Psmb/Newsletter/Controller/NewsletterController.php
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
<?php
namespace Psmb\Newsletter\Controller;

use TYPO3\Flow\Annotations as Flow;
use Psmb\Newsletter\Domain\Model\Subscriber;
use Psmb\Newsletter\Domain\Repository\SubscriberRepository;
use Psmb\Newsletter\Service\FusionMailService;
use TYPO3\Flow\Mvc\View\JsonView;
use TYPO3\Flow\I18n\Service as I18nService;
use TYPO3\Flow\I18n\Translator;
use TYPO3\Flow\Mvc\Controller\ActionController;
use TYPO3\Flow\Annotations as Flow;
use TYPO3\TYPO3CR\Domain\Model\NodeInterface;

class NewsletterController extends ActionController
Expand Down Expand Up @@ -49,6 +49,11 @@ class NewsletterController extends ActionController
'json' => JsonView::class
);

/**
* Get manual subscriptions for AJAX sending
*
* @return void
*/
public function getSubscriptionsAction() {
$manualSubscriptions = array_filter($this->subscriptions, function ($item) {
return $item['interval'] == 'manual';
Expand All @@ -68,20 +73,12 @@ public function getSubscriptionsAction() {
*/
public function sendAction($subscription, NodeInterface $node)
{
$this->fusionMailService->setupObject($this->getControllerContext(), $this->request);
$subscriptions = array_filter($this->subscriptions, function ($item) use ($subscription) {
return $item['identifier'] == $subscription;
});
$nestedLetters = array_map(function ($subscription) use ($node) {
return $this->generateLettersForSubscription($subscription, $node);
}, $subscriptions);
$letters = array_reduce($nestedLetters, function ($acc, $item) {
return array_merge($acc, $item);
}, []);

array_map(function($letter) {
$this->fusionMailService->sendLetter($letter);
}, $letters);
array_walk($subscriptions, function ($subscription) use ($node) {
$this->sendLettersForSubscription($subscription, $node);
});
$this->view->assign('value', ['status' => 'success']);
}

Expand All @@ -95,17 +92,16 @@ public function sendAction($subscription, NodeInterface $node)
*/
public function testSendAction($subscription, NodeInterface $node, $email)
{
$this->fusionMailService->setupObject($this->getControllerContext(), $this->request);
$subscriptions = array_filter($this->subscriptions, function ($item) use ($subscription) {
return $item['identifier'] == $subscription;
});
$subscription = reset($subscriptions);

$subscriber = new Subscriber();
$subscriber->setEmail($email);
$subscriber->setName('Test User');

$letter = $this->fusionMailService->generateSubscriptionLetter($subscriber, reset($subscriptions), $node);
$this->fusionMailService->sendLetter($letter);
$this->fusionMailService->generateSubscriptionLetterAndSend($subscriber, $subscription, $node);

$this->view->assign('value', ['status' => 'success']);
}
Expand All @@ -115,16 +111,15 @@ public function testSendAction($subscription, NodeInterface $node, $email)
*
* @param array $subscription
* @param NodeInterface $node Node of the current newsletter item
* @return array Array of letters
* @return void
*/
protected function generateLettersForSubscription($subscription, $node)
protected function sendLettersForSubscription($subscription, $node)
{
$subscribers = $this->subscriberRepository->findBySubscriptionId($subscription['identifier'])->toArray();

$letters = array_map(function ($subscriber) use ($subscription, $node) {
return $this->fusionMailService->generateSubscriptionLetter($subscriber, $subscription, $node);
}, $subscribers);
return array_filter($letters);
array_walk($subscribers, function ($subscriber) use ($subscription, $node) {
$this->fusionMailService->generateSubscriptionLetterAndSend($subscriber, $subscription, $node);
});
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -179,10 +179,9 @@ public function feedbackAction()
*
* @param Subscriber $subscriber
* @param string $hash
* @return int
* @return void
*/
protected function sendActivationLetter(Subscriber $subscriber, $hash) {
$this->fusionMailService->setupObject($this->controllerContext, $this->request);
$activationLetter = $this->fusionMailService->generateActivationLetter($subscriber, $hash);
$this->fusionMailService->sendLetter($activationLetter);
}
Expand Down
91 changes: 84 additions & 7 deletions Classes/Psmb/Newsletter/Service/FusionMailService.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,22 @@
namespace Psmb\Newsletter\Service;

use TYPO3\Flow\Annotations as Flow;
use Flowpack\JobQueue\Common\Annotations as Job;
use Psmb\Newsletter\Domain\Model\Subscriber;
use Psmb\Newsletter\View\FusionView;
use TYPO3\Flow\Mvc\ActionRequest;
use TYPO3\Flow\Mvc\Controller\ControllerContext;
use TYPO3\Flow\Mvc\Routing\UriBuilder;
use TYPO3\Neos\Domain\Service\ContentDimensionPresetSourceInterface;
use TYPO3\SwiftMailer\Message;
use TYPO3\TYPO3CR\Domain\Model\Node;
use TYPO3\TYPO3CR\Domain\Model\NodeInterface;
use TYPO3\TYPO3CR\Domain\Service\ContextFactoryInterface;
use Flowpack\JobQueue\Common\Annotations as Job;
use Psmb\Newsletter\Domain\Repository\SubscriberRepository;
use TYPO3\Flow\Http\Request;
use TYPO3\Flow\Http\Response;
use TYPO3\Flow\Http\Uri;
use TYPO3\Flow\Mvc\Controller\Arguments;


/**
* @Flow\Scope("singleton")
Expand Down Expand Up @@ -43,16 +49,69 @@ class FusionMailService {
protected $globalSettings;

/**
* @param ControllerContext $controllerContext
* @param ActionRequest $request
* @Flow\Inject
* @var SubscriberRepository
*/
public function setupObject(ControllerContext $controllerContext, ActionRequest $request) {
protected $subscriberRepository;

/**
* @Flow\InjectConfiguration(package="TYPO3.Flow", path="http.baseUri")
* @var string
*/
protected $baseUri;

/**
* @Flow\InjectConfiguration(path="subscriptions")
* @var array
*/
protected $subscriptions;

/**
* We can't do this in constructor as we need configuration to be injected
*/
public function initializeObject() {
$request = $this->createRequest();
$controllerContext = $this->createControllerContext($request);
$this->view->setControllerContext($controllerContext);
$this->uriBuilder->setRequest($request);
}

/**
* @Job\Defer(queueName="psmb-newsletter")
* @return ActionRequest
*/
protected function createRequest() {
$_SERVER['FLOW_REWRITEURLS'] = 1;
$httpRequest = Request::createFromEnvironment();
if ($this->baseUri) {
$baseUri = new Uri($this->baseUri);
$httpRequest->setBaseUri($baseUri);
}
$request = new ActionRequest($httpRequest);
$request->setFormat('html');
return $request;
}

/**
* Creates a controller content context for live dimension
*
* @param ActionRequest $request
* @return ControllerContext
*/
protected function createControllerContext($request)
{
$uriBuilder = new UriBuilder();
$uriBuilder->setRequest($request);
$controllerContext = new ControllerContext(
$request,
new Response(),
new Arguments([]),
$uriBuilder
);
return $controllerContext;
}

/**
* Just a simple wrapper over SwiftMailer
*
* @param array $letter
* @throws \Exception
Expand Down Expand Up @@ -80,7 +139,7 @@ public function sendLetter($letter)
throw new \Exception('"senderAddress" must be set.', 1327060211);
}

$mail = new \TYPO3\SwiftMailer\Message();
$mail = new Message();
$mail
->setFrom(array($senderAddress => $senderName))
->setTo(array($recipientAddress => $recipientName))
Expand Down Expand Up @@ -157,6 +216,23 @@ public function generateSubscriptionLetter(Subscriber $subscriber, $subscription
return $this->view->render();
}

/**
* Generate a letter for given subscriber and subscription and sends it. Async.
*
* @Job\Defer(queueName="psmb-newsletter")
* @param Subscriber $subscriber
* @param array $subscription
* @param null|NodeInterface $node
* @return void
*/
public function generateSubscriptionLetterAndSend(Subscriber $subscriber, $subscription, $node = NULL)
{
$letter = $this->generateSubscriptionLetter($subscriber, $subscription, $node);
if ($letter) {
$this->sendLetter($letter);
}
}

/**
* @param array $dimensions
* @return Node
Expand All @@ -172,4 +248,5 @@ protected function getSiteNode($dimensions = [])
$context = $this->contextFactory->create($contextProperties);
return $context->getCurrentSiteNode();
}

}
2 changes: 1 addition & 1 deletion Classes/Psmb/Newsletter/View/FusionView.php
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ protected function getTypoScriptRuntime(NodeInterface $siteNode)
*
* @param string $key
* @param mixed $value
* @return FusionView
* @return AbstractView
*/
public function assign($key, $value)
{
Expand Down
Loading

0 comments on commit 74e7f95

Please sign in to comment.