Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Todo reminder notification #73

Merged
merged 8 commits into from
Mar 19, 2016
4 changes: 3 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@
"zendframework/zend-expressive-helpers": "^2.0",
"zendframework/zend-expressive-zendviewrenderer": "^1.0.1",
"zendframework/zend-filter": "^2.6",
"zendframework/zend-servicemanager" : "^2.7.5 || ^3.0.3"
"zendframework/zend-servicemanager" : "^2.7.5 || ^3.0.3",
"zendframework/zend-stdlib": "^2.7",
"zendframework/zend-mail": "^2.6"
},
"require-dev" : {
"fabpot/php-cs-fixer": "^1.9.3",
Expand Down
27 changes: 16 additions & 11 deletions config/autoload/dependencies.global.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,30 @@
Helper\UrlHelper::class => Helper\UrlHelperFactory::class,
'doctrine.connection.default' => \Prooph\ProophessorDo\Container\Infrastructure\DoctrineDbalConnectionFactory::class,
// Action middleware
\Prooph\ProophessorDo\App\Action\Home::class => \Prooph\ProophessorDo\Container\App\Action\HomeFactory::class,
\Prooph\ProophessorDo\App\Action\UserList::class => \Prooph\ProophessorDo\Container\App\Action\UserListFactory::class,
\Prooph\ProophessorDo\App\Action\Home::class => \Prooph\ProophessorDo\Container\App\Action\HomeFactory::class,
\Prooph\ProophessorDo\App\Action\UserList::class => \Prooph\ProophessorDo\Container\App\Action\UserListFactory::class,
\Prooph\ProophessorDo\App\Action\UserRegistration::class => \Prooph\ProophessorDo\Container\App\Action\UserRegistrationFactory::class,
\Prooph\ProophessorDo\App\Action\UserTodoList::class => \Prooph\ProophessorDo\Container\App\Action\UserTodoListFactory::class,
\Prooph\ProophessorDo\App\Action\UserTodoForm::class => \Prooph\ProophessorDo\Container\App\Action\UserTodoFormFactory::class,
\Prooph\ProophessorDo\App\Action\UserTodoList::class => \Prooph\ProophessorDo\Container\App\Action\UserTodoListFactory::class,
\Prooph\ProophessorDo\App\Action\UserTodoForm::class => \Prooph\ProophessorDo\Container\App\Action\UserTodoFormFactory::class,
// Model
\Prooph\ProophessorDo\Model\User\Handler\RegisterUserHandler::class => \Prooph\ProophessorDo\Container\Model\User\RegisterUserHandlerFactory::class,
\Prooph\ProophessorDo\Model\User\UserCollection::class => \Prooph\ProophessorDo\Container\Infrastructure\Repository\EventStoreUserCollectionFactory::class,
\Prooph\ProophessorDo\Model\Todo\Handler\PostTodoHandler::class => \Prooph\ProophessorDo\Container\Model\Todo\PostTodoHandlerFactory::class,
\Prooph\ProophessorDo\Model\Todo\Handler\MarkTodoAsDoneHandler::class => \Prooph\ProophessorDo\Container\Model\Todo\MarkTodoAsDoneHandlerFactory::class,
\Prooph\ProophessorDo\Model\Todo\Handler\ReopenTodoHandler::class => \Prooph\ProophessorDo\Container\Model\Todo\ReopenTodoHandlerFactory::class,
\Prooph\ProophessorDo\Model\User\UserCollection::class => \Prooph\ProophessorDo\Container\Infrastructure\Repository\EventStoreUserCollectionFactory::class,
\Prooph\ProophessorDo\Model\Todo\Handler\PostTodoHandler::class => \Prooph\ProophessorDo\Container\Model\Todo\PostTodoHandlerFactory::class,
\Prooph\ProophessorDo\Model\Todo\Handler\MarkTodoAsDoneHandler::class => \Prooph\ProophessorDo\Container\Model\Todo\MarkTodoAsDoneHandlerFactory::class,
\Prooph\ProophessorDo\Model\Todo\Handler\ReopenTodoHandler::class => \Prooph\ProophessorDo\Container\Model\Todo\ReopenTodoHandlerFactory::class,
\Prooph\ProophessorDo\Model\Todo\Handler\AddDeadlineToTodoHandler::class => \Prooph\ProophessorDo\Container\Model\Todo\AddDeadlineToTodoHandlerFactory::class,
\Prooph\ProophessorDo\Model\Todo\Handler\AddReminderToTodoHandler::class => \Prooph\ProophessorDo\Container\Model\Todo\AddReminderToTodoHandlerFactory::class,
\Prooph\ProophessorDo\Model\Todo\TodoList::class => \Prooph\ProophessorDo\Container\Infrastructure\Repository\EventStoreTodoListFactory::class,
\Prooph\ProophessorDo\Model\Todo\Handler\RemindTodoAssigneeHandler::class => \Prooph\ProophessorDo\Container\Model\Todo\RemindTodoAssigneeHandlerFactory::class,
\Prooph\ProophessorDo\Model\Todo\TodoList::class => \Prooph\ProophessorDo\Container\Infrastructure\Repository\EventStoreTodoListFactory::class,
// Projections
\Prooph\ProophessorDo\Projection\User\UserProjector::class => \Prooph\ProophessorDo\Container\Projection\User\UserProjectorFactory::class,
\Prooph\ProophessorDo\Projection\User\UserFinder::class => \Prooph\ProophessorDo\Container\Projection\User\UserFinderFactory::class,
\Prooph\ProophessorDo\Projection\User\UserFinder::class => \Prooph\ProophessorDo\Container\Projection\User\UserFinderFactory::class,
\Prooph\ProophessorDo\Projection\Todo\TodoProjector::class => \Prooph\ProophessorDo\Container\Projection\Todo\TodoProjectorFactory::class,
\Prooph\ProophessorDo\Projection\Todo\TodoFinder::class => \Prooph\ProophessorDo\Container\Projection\Todo\TodoFinderFactory::class,
\Prooph\ProophessorDo\Projection\Todo\TodoFinder::class => \Prooph\ProophessorDo\Container\Projection\Todo\TodoFinderFactory::class,
\Prooph\ProophessorDo\Projection\Todo\TodoReminderFinder::class => \Prooph\ProophessorDo\Container\Projection\Todo\TodoReminderFinderFactory::class,
\Prooph\ProophessorDo\Projection\Todo\TodoReminderProjector::class => \Prooph\ProophessorDo\Container\Projection\Todo\TodoReminderProjectorFactory::class,
// Subscriber
\Prooph\ProophessorDo\App\Mail\SendTodoReminderMailSubscriber::class => \Prooph\ProophessorDo\Container\App\Mail\SendTodoReminderMailSubscriberFactory::class,
],
],
];
20 changes: 20 additions & 0 deletions config/autoload/mail_connection.local.php.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php
return [
'proophessor-do' => [
'mail' => [
'transport' => 'in_memory', // smtp or in_memory (default)
// uncomment if you want to use smtp. Preset for gmail
// 'smtp' => [
// 'name' => 'gmail.com',
// 'host' => 'smtp.gmail.com',
// 'port' => 587,
// 'connection_class' => 'plain',
// 'connection_config' => [
// 'username' => 'YOUR_USERNAME_HERE',
// 'password' => 'YOUR_PASSWORD_HERE',
// 'ssl' => 'tls',
// ],
// ],
]
]
];
7 changes: 7 additions & 0 deletions config/autoload/prooph.global.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
\Prooph\ProophessorDo\Model\Todo\Command\ReopenTodo::class => \Prooph\ProophessorDo\Model\Todo\Handler\ReopenTodoHandler::class,
\Prooph\ProophessorDo\Model\Todo\Command\AddDeadlineToTodo::class => \Prooph\ProophessorDo\Model\Todo\Handler\AddDeadlineToTodoHandler::class,
\Prooph\ProophessorDo\Model\Todo\Command\AddReminderToTodo::class => \Prooph\ProophessorDo\Model\Todo\Handler\AddReminderToTodoHandler::class,
\Prooph\ProophessorDo\Model\Todo\Command\RemindTodoAssignee::class => \Prooph\ProophessorDo\Model\Todo\Handler\RemindTodoAssigneeHandler::class,
],
],
],
Expand Down Expand Up @@ -82,6 +83,12 @@
],
\Prooph\ProophessorDo\Model\Todo\Event\ReminderWasAddedToTodo::class => [
\Prooph\ProophessorDo\Projection\Todo\TodoProjector::class,
\Prooph\ProophessorDo\Projection\Todo\TodoReminderProjector::class,
],
\Prooph\ProophessorDo\Model\Todo\Event\TodoAssigneeWasReminded::class => [
\Prooph\ProophessorDo\Projection\Todo\TodoProjector::class,
\Prooph\ProophessorDo\Projection\Todo\TodoReminderProjector::class,
\Prooph\ProophessorDo\App\Mail\SendTodoReminderMailSubscriber::class,
],
],
],
Expand Down
28 changes: 28 additions & 0 deletions migrations/Version20160308110616.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace Prooph\ProophessorDo\Migrations;

use Doctrine\DBAL\Migrations\AbstractMigration;
use Doctrine\DBAL\Schema\Schema;
use Prooph\ProophessorDo\Projection\Table;

/**
* Auto-generated Migration: Please modify to your needs!
*/
class Version20160308110616 extends AbstractMigration
{
public function up(Schema $schema)
{
$user = $schema->createTable(Table::TODO_REMINDER);

$user->addColumn('todo_id', 'string', ['length' => 36]);
$user->addColumn('reminder', 'string', ['length' => 30]);
$user->addColumn('status', 'string', ['length' => 10]);
$user->setPrimaryKey(['todo_id']);
}

public function down(Schema $schema)
{
$schema->dropTable(Table::TODO_REMINDER);
}
}
39 changes: 39 additions & 0 deletions scripts/send_reminder_notification.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php
/**
* This script looks for todos with open reminders and reminds the assignees
*/
namespace {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should have proophessor-do namespace, no?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just tried to match the other scripts in the folder. Dont mind adding the namespace


use Prooph\ProophessorDo\Model\Todo\Command\RemindTodoAssignee;
use Prooph\ProophessorDo\Model\Todo\TodoId;
use Prooph\ProophessorDo\Model\Todo\TodoReminder;
use Prooph\ProophessorDo\Projection\Todo\TodoReminderFinder;
use Prooph\ServiceBus\CommandBus;

chdir(dirname(__DIR__));

// Setup autoloading
require 'vendor/autoload.php';

$container = require 'config/container.php';

$commandBus = $container->get(CommandBus::class);
$todoReminderFinder = $container->get(TodoReminderFinder::class);

$todoReminder = $todoReminderFinder->findOpen();

if (!$todoReminder) {
echo "Nothing to do. Exiting.\n";
exit;
}

foreach ($todoReminder as $reminder) {
echo "Send reminder for Todo with id {$reminder->todo_id}.\n";
$commandBus->dispatch(
RemindTodoAssignee::forTodo(
TodoId::fromString($reminder->todo_id), TodoReminder::fromString($reminder->reminder, $reminder->status)
));
}

echo "Done!\n";
}
59 changes: 59 additions & 0 deletions src/App/Mail/SendTodoReminderMailSubscriber.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php
namespace Prooph\ProophessorDo\App\Mail;

use Prooph\ProophessorDo\Model\Todo\Event\TodoAssigneeWasReminded;
use Prooph\ProophessorDo\Projection\Todo\TodoFinder;
use Prooph\ProophessorDo\Projection\User\UserFinder;
use Zend\Mail\Transport\TransportInterface;
use Zend\Mail;

/**
* Class SendTodoReminderMailSubscriber
*
* @package Prooph\ProophessorDo\App\Mail
* @author Roman Sachse <[email protected]>
*/
final class SendTodoReminderMailSubscriber
{
/**
* @var UserFinder
*/
private $userFinder;
/**
* @var TodoFinder
*/
private $todoFinder;
/**
* @var TransportInterface
*/
private $mailer;

/**
* @param UserFinder $userFinder
* @param TodoFinder $todoFinder
* @param TransportInterface $mailer
*/
public function __construct(UserFinder $userFinder, TodoFinder $todoFinder, TransportInterface $mailer)
{
$this->userFinder = $userFinder;
$this->todoFinder = $todoFinder;
$this->mailer = $mailer;
}

/**
* @param TodoAssigneeWasReminded $event
*/
public function __invoke(TodoAssigneeWasReminded $event)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

phpdoc missing

{
$user = $this->userFinder->findById($event->userId()->toString());
$todo = $this->todoFinder->findById($event->todoId()->toString());

$mail = new Mail\Message();
$mail->setBody("Hello {$user->name}. This a reminder for '{$todo->text}'. Don't be lazy!");
$mail->setFrom('[email protected]', 'Proophessor-do');
$mail->addTo($user->email, $user->name);
$mail->setSubject('Proophessor-do Todo Reminder');

$this->mailer->send($mail);
}
}
95 changes: 95 additions & 0 deletions src/Container/App/Mail/SendTodoReminderMailSubscriberFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<?php

namespace Prooph\ProophessorDo\Container\App\Mail;

use Interop\Config\ConfigurationTrait;
use Interop\Config\ProvidesDefaultOptions;
use Interop\Config\RequiresConfig;
use Interop\Config\RequiresMandatoryOptions;
use Interop\Container\ContainerInterface;
use Prooph\ProophessorDo\App\Mail\SendTodoReminderMailSubscriber;
use Prooph\ProophessorDo\Projection\Todo\TodoFinder;
use Prooph\ProophessorDo\Projection\User\UserFinder;
use Zend\Mail\Transport\InMemory as InMemoryTransport;
use Zend\Mail\Transport\Smtp as SmtpTransport;
use Zend\Mail\Transport\SmtpOptions;


/**
* Class RemindTodoAssigneeHandlerFactory
*
* @package Prooph\ProophessorDo\Container\Model\Todo
* @author Roman Sachse <[email protected]>
*/
final class SendTodoReminderMailSubscriberFactory implements RequiresConfig, RequiresMandatoryOptions, ProvidesDefaultOptions
{
use ConfigurationTrait;

/**
* @inheritdoc
*/
public function vendorName()
{
return 'proophessor-do';
}

/**
* @inheritdoc
*/
public function packageName()
{
return 'mail';
}

/**
* @inheritdoc
*/
public function mandatoryOptions()
{
return ['transport'];
}

/**
* @inheritdoc
*/
public function defaultOptions()
{
return ['transport' => 'in_memory'];
}

/**
* @param ContainerInterface $container
* @return SendTodoReminderMailSubscriber
*/
public function __invoke(ContainerInterface $container)
{
return new SendTodoReminderMailSubscriber(
$container->get(UserFinder::class),
$container->get(TodoFinder::class),
$this->getTransport($container->get('config'))
);
}

/**
* @param $config
* @return SmtpTransport
*/
private function getTransport($config)
{
$config = $this->optionsWithFallback($config);

switch ($config['transport']) {
case 'in_memory':
return new InMemoryTransport();

case 'smtp':
$transport = new SmtpTransport();
$transport->setOptions(new SmtpOptions($config['smtp']));

return $transport;
}
throw new \InvalidArgumentException(
"Transport of type '{$config['transport']}' not known (use in_memory or smtp)"
);
}
}
26 changes: 26 additions & 0 deletions src/Container/Model/Todo/RemindTodoAssigneeHandlerFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

namespace Prooph\ProophessorDo\Container\Model\Todo;

use Interop\Container\ContainerInterface;
use Prooph\ProophessorDo\Model\Todo\Handler\RemindTodoAssigneeHandler;
use Prooph\ProophessorDo\Model\Todo\TodoList;
use Prooph\ProophessorDo\Projection\Todo\TodoFinder;

/**
* Class RemindTodoAssigneeHandlerFactory
*
* @package Prooph\ProophessorDo\Container\Model\Todo
* @author Roman Sachse <[email protected]>
*/
final class RemindTodoAssigneeHandlerFactory
{
/**
* @param ContainerInterface $container
* @return RemindTodoAssigneeHandlerFactory
*/
public function __invoke(ContainerInterface $container)
{
return new RemindTodoAssigneeHandler($container->get(TodoList::class), $container->get(TodoFinder::class));
}
}
32 changes: 32 additions & 0 deletions src/Container/Projection/Todo/TodoReminderFinderFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php
/*
* This file is part of prooph/proophessor.
* (c) 2014-2015 prooph software GmbH <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* Date: 5/4/15 - 8:53 PM
*/
namespace Prooph\ProophessorDo\Container\Projection\Todo;

use Interop\Container\ContainerInterface;
use Prooph\ProophessorDo\Projection\Todo\TodoReminderFinder;

/**
* Class TodoFinderFactory
*
* @package Prooph\ProophessorDo\Projection\Todo
* @author Roman Sachse <[email protected]>
*/
final class TodoReminderFinderFactory
{
/**
* @param ContainerInterface $container
* @return TodoReminderFinder
*/
public function __invoke(ContainerInterface $container)
{
return new TodoReminderFinder($container->get('doctrine.connection.default'));
}
}
Loading