Skip to content

Commit

Permalink
FEATURE: external data-sources
Browse files Browse the repository at this point in the history
  • Loading branch information
dimaip committed Feb 28, 2018
1 parent 8298308 commit 62c6851
Show file tree
Hide file tree
Showing 8 changed files with 221 additions and 10 deletions.
22 changes: 16 additions & 6 deletions Classes/Psmb/Newsletter/Controller/NewsletterController.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
use Flowpack\JobQueue\Common\Annotations as Job;
use Neos\Flow\Annotations as Flow;
use Psmb\Newsletter\Domain\Model\Subscriber;
use Psmb\Newsletter\Domain\Repository\SubscriberRepository;
use Psmb\Newsletter\Service\FusionMailService;
use Psmb\Newsletter\Service\SubscribersService;
use Neos\Flow\Mvc\View\JsonView;
use Neos\Flow\I18n\Service as I18nService;
use Neos\Flow\I18n\Translator;
Expand All @@ -25,6 +25,7 @@ class NewsletterController extends ActionController
* @var Translator
*/
protected $translator;

/**
* @Flow\Inject
* @var FusionMailService
Expand All @@ -33,9 +34,15 @@ class NewsletterController extends ActionController

/**
* @Flow\Inject
* @var SubscriberRepository
* @var SubscribersService
*/
protected $subscriberRepository;
protected $subscribersService;

/**
* @Flow\Inject
* @var \Neos\Flow\Log\SystemLoggerInterface
*/
protected $systemLogger;

/**
* @Flow\InjectConfiguration(path="subscriptions")
Expand Down Expand Up @@ -128,11 +135,14 @@ public function testSendAction($subscription, NodeInterface $node, $email)
*/
public function sendLettersForSubscription($subscription, $node)
{
$subscribers = $this->subscriberRepository->findBySubscriptionId($subscription['identifier'])->toArray();
$subscribers = $this->subscribersService->getSubscribers($subscription);

array_walk($subscribers, function ($subscriber) use ($subscription, $node) {
$this->fusionMailService->generateSubscriptionLetterAndSend($subscriber, $subscription, $node);
try {
$this->fusionMailService->generateSubscriptionLetterAndSend($subscriber, $subscription, $node);
} catch (\Exception $e) {
$this->systemLogger->log($e->getMessage(), \LOG_ERR);
}
});
}

}
33 changes: 33 additions & 0 deletions Classes/Psmb/Newsletter/Service/DataSource/AbstractDataSource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php
namespace Psmb\Newsletter\Service\DataSource;

/**
* Data source interface for getting data.
*
* @api
*/
abstract class AbstractDataSource implements DataSourceInterface
{

/**
* The identifier of the operation
*
* @var string
* @api
*/
protected static $identifier = null;

/**
* @return string the short name of the operation
* @api
* @throws \Exception
*/
public static function getIdentifier()
{
if (!is_string(static::$identifier)) {
throw new \Exception('Identifier in class ' . __CLASS__ . ' is empty.', 1414091236);
}

return static::$identifier;
}
}
29 changes: 29 additions & 0 deletions Classes/Psmb/Newsletter/Service/DataSource/DataSourceInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php
namespace Psmb\Newsletter\Service\DataSource;

/**
* Data source interface for providing generic data
*
* This is used in the user interface to generate dynamic option lists.
*
* @api
*/
interface DataSourceInterface
{
/**
* @return string The identifier of the data source
* @api
*/
public static function getIdentifier();

/**
* Get data
*
* The return value must be JSON serializable data structure.
*
* @param array $subscription Subscription data
* @return mixed data
* @api
*/
public function getData(array $subscription);
}
26 changes: 26 additions & 0 deletions Classes/Psmb/Newsletter/Service/DataSource/JsonDataSource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php
namespace Psmb\Newsletter\Service\DataSource;

use Neos\Flow\Annotations as Flow;

class JsonDataSource extends AbstractDataSource
{
/**
* @var string
*/
protected static $identifier = 'Json';

/**
* Get subscribers from an external json endpoint
*
* {@inheritdoc}
*/
public function getData(array $subscription)
{
if (!isset($subscription['dataSourceOptions']['uri'])) {
throw new \Exception('dataSourceOptions.uri must be set for the Json datasource' . print_r($subscription, 1));
}
$response = file_get_contents($subscription['dataSourceOptions']['uri']);
return json_decode($response, true);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php
namespace Psmb\Newsletter\Service\DataSource;

use Neos\Flow\Annotations as Flow;
use Psmb\Newsletter\Domain\Repository\SubscriberRepository;

class RepositoryDataSource extends AbstractDataSource
{
/**
* @Flow\Inject
* @var SubscriberRepository
*/
protected $subscriberRepository;

/**
* @var string
*/
protected static $identifier = 'Repository';

/**
* Get subscribers from the repository
*
* {@inheritdoc}
*/
public function getData(array $subscription)
{
$subscribers = $this->subscriberRepository->findBySubscriptionId($subscription['identifier'])->toArray();
}
}
8 changes: 4 additions & 4 deletions Classes/Psmb/Newsletter/Service/FusionMailService.php
Original file line number Diff line number Diff line change
Expand Up @@ -205,12 +205,12 @@ public function sendActivationLetter(Subscriber $subscriber, $hash)
/**
* Generate a letter for given subscriber and subscription
*
* @param Subscriber $subscriber
* @param array|Subscriber $subscriber
* @param array $subscription
* @param null|NodeInterface $node
* @return array
*/
public function generateSubscriptionLetter(Subscriber $subscriber, $subscription, $node = NULL)
public function generateSubscriptionLetter($subscriber, $subscription, $node = NULL)
{
$dimensions = isset($subscription['dimensions']) ? $subscription['dimensions'] : null;
$siteNode = $this->getSiteNode($dimensions);
Expand All @@ -230,12 +230,12 @@ public function generateSubscriptionLetter(Subscriber $subscriber, $subscription
* Generate a letter for given subscriber and subscription and sends it. Async.
*
* @Job\Defer(queueName="psmb-newsletter")
* @param Subscriber $subscriber
* @param array|Subscriber $subscriber
* @param array $subscription
* @param null|NodeInterface $node
* @return void
*/
public function generateSubscriptionLetterAndSend(Subscriber $subscriber, $subscription, $node = NULL)
public function generateSubscriptionLetterAndSend($subscriber, $subscription, $node = NULL)
{
$letter = $this->generateSubscriptionLetter($subscriber, $subscription, $node);
if ($letter) {
Expand Down
66 changes: 66 additions & 0 deletions Classes/Psmb/Newsletter/Service/SubscribersService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php
namespace Psmb\Newsletter\Service;

use Neos\Flow\Annotations as Flow;
use Neos\Flow\ObjectManagement\ObjectManagerInterface;
use Neos\Flow\Reflection\ReflectionService;
use Psmb\Newsletter\Service\DataSource\DataSourceInterface;

/**
* @Flow\Scope("singleton")
*/
class SubscribersService {

/**
* @Flow\Inject
* @var ObjectManagerInterface
*/
protected $objectManager;

/**
* Get subscribers data
*
* @param array $subscription
* @return array Subscribers data
*/
public function getSubscribers($subscription)
{
$dataSources = static::getDataSources($this->objectManager);
// throw new \Exception(print_r($dataSources, 1));
$dataSourceIdentifier = $subscription['dataSourceIdentifier'] ?? 'Repository';

if (!isset($dataSources[$dataSourceIdentifier])) {
throw new \Exception(sprintf('Data source with identifier "%s" does not exist.', $dataSourceIdentifier), 1414082186);
}

/** @var $dataSource DataSourceInterface */
$dataSource = new $dataSources[$dataSourceIdentifier];

return $dataSource->getData($subscription);
}

/**
* Get available data source implementations
*
* @param ObjectManagerInterface $objectManager
* @return array Data source class names indexed by identifier
* @Flow\CompileStatic
*/
public static function getDataSources($objectManager)
{
$reflectionService = $objectManager->get(ReflectionService::class);

$dataSources = array();
$dataSourceClassNames = $reflectionService->getAllImplementationClassNamesForInterface(DataSourceInterface::class);
/** @var $dataSourceClassName DataSourceInterface */
foreach ($dataSourceClassNames as $dataSourceClassName) {
$identifier = $dataSourceClassName::getIdentifier();
if (isset($dataSources[$identifier])) {
throw new \Exception(sprintf('Data source with identifier "%s" is already defined in class %s.', $identifier, $dataSourceClassName), 14140348185);
}
$dataSources[$identifier] = $dataSourceClassName;
}

return $dataSources;
}
}
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,24 @@ Here's a quick example how to create CSV exports from mysql:
SELECT email, name INTO OUTFILE '/path/test.csv' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n' FROM yourTable;
```

## External Datasources

The default datasource for fetching subscribers has an identifier `Repository`. It fetches all subscribers subscribed via the default subscription plugin.

You may fetch subscribers from an external JSON source via the `Json` datasource. Here's an example:

```
Psmb:
Newsletter:
subscriptions:
-
dataSourceIdentifier: 'Json'
dataSourceOptions:
uri: 'http://some.host/some-url'
```

Alternatively you may provide your custom datasources. See implementation of JsonDataSource.php to see how to do that.

## Acknowledgements

This is my first Flow package, and it wouldn't have been possible without a support of the community by answering dozens of n00b questions on Slack, by Christian Müller in particular.

0 comments on commit 62c6851

Please sign in to comment.