Commit d6ef9926 authored by Korko's avatar Korko
Browse files

Events

parent b550ed16
Pipeline #224560 passed with stage
in 6 minutes and 59 seconds
<?php
namespace App\Events;
use App\Draw;
use Illuminate\Queue\SerializesModels;
class DrawDone
{
use SerializesModels;
public $draw;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct(Draw $draw)
{
$this->draw = $draw;
}
}
......@@ -4,8 +4,8 @@ namespace App\Http\Controllers;
use App\Exceptions\SolverException;
use App\Http\Requests\RandomFormRequest;
use App\Services\DrawHandler;
use Arr;
use DrawHandler;
use Illuminate\Http\Request;
class RandomFormController extends Controller
......@@ -40,12 +40,12 @@ class RandomFormController extends Controller
$dataExpiration = $request->input('data-expiration');
$mailContent = [
'title' => $request->input('title'),
'body' => $request->input('content-email'),
];
$title = $request->input('title');
$body = $request->input('content-email');
return (new DrawHandler())->contactParticipants($participants, $mailContent, $dataExpiration);
return DrawHandler::toParticipants($participants)
->expiresAt($dataExpiration)
->sendMail($title, $body);
}
protected function formatParticipants(array $participants): array
......@@ -53,13 +53,6 @@ class RandomFormController extends Controller
for ($i = 0; $i < count($participants); $i++) {
$participant = &$participants[$i];
if (! empty($participant['phone'])) {
if (substr($participant['phone'], 0, 1) === '0') {
$participant['phone'] = substr($participant['phone'], 1);
}
$participant['phone'] = '+33'.$participant['phone'];
}
$participant['exclusions'] = array_map('intval', Arr::get($participant, 'exclusions', []));
}
unset($participant);
......
<?php
namespace App\Listeners;
use App\Exceptions\SolverException;
use App\Events\DrawDone;
use App\Jobs\SendMail;
use App\Mail\OrganizerFinalRecap;
use App\Mail\OrganizerRecap;
use Facades\App\Services\HatSolver as Solver;
class ContactOrganizer
{
/**
* Handle the event.
*
* @param \App\Events\DrawDone $event
* @return void
*/
public function handle(DrawDone $event)
{
SendMail::dispatch($event->draw->organizer, new OrganizerRecap($event->draw));
$event->draw->participants->each(function (&$participant) {
$participant->exclusions[] = $participant->target->id;
});
try {
// Check if there's a solution with the previous exclusions + the actual target
Solver::one($event->draw->participants->all(), $event->draw->participants->pluck('exclusions', 'id')->all());
} catch (SolverException $e) {
// If not, reset all the exclusions
$event->draw->participants->each(function (&$participant) {
$participant->exclusions = [];
});
}
SendMail::dispatch($event->draw->organizer, new OrganizerFinalRecap($event->draw))
->delay($event->draw->expires_at->addDays(2));
}
}
<?php
namespace App\Listeners;
use App\Events\DrawDone;
use App\Jobs\SendMail;
use App\Mail\TargetDrawn;
use Metrics;
class ContactParticipants
{
/**
* Handle the event.
*
* @param object $event
* @return void
*/
public function handle(DrawDone $event)
{
foreach ($event->draw->participants as $participant) {
Metrics::increment('email');
SendMail::dispatch($participant, new TargetDrawn($participant));
}
}
}
......@@ -12,6 +12,7 @@ class EventServiceProvider extends ServiceProvider
* @var array
*/
protected $listen = [
//
];
/**
......@@ -25,4 +26,14 @@ class EventServiceProvider extends ServiceProvider
//
}
/**
* Determine if events and listeners should be automatically discovered.
*
* @return bool
*/
public function shouldDiscoverEvents()
{
return true;
}
}
......@@ -3,12 +3,8 @@
namespace App\Services;
use App\Draw;
use App\Exceptions\SolverException;
use App\Jobs\SendMail;
use App\Events\DrawDone;
use App\Mail as MailModel;
use App\Mail\OrganizerFinalRecap;
use App\Mail\OrganizerRecap;
use App\Mail\TargetDrawn;
use App\Participant;
use Arr;
use Facades\App\Services\HatSolver as Solver;
......@@ -16,19 +12,49 @@ use Metrics;
class DrawHandler
{
public function contactParticipants(array $participants, array $mailContent, $dataExpiration): void
protected $participants;
protected $hat;
protected $expirationDate;
public function toParticipants(array $participants): self
{
$hat = Solver::one($participants, array_column($participants, 'exclusions'));
$this->participants = $participants;
$this->hat = Solver::one($participants, array_column($participants, 'exclusions'));
return $this;
}
public function expiresAt($expirationDate): self
{
$this->expirationDate = $expirationDate;
return $this;
}
public function sendMail($title, $body): void
{
$draw = $this->createDraw($title, $body, $this->expirationDate ?: date('Y-m-d', strtotime('+2 days')));
Metrics::increment('draws');
Metrics::increment('participants', count($participants));
$this->createParticipants($draw, $this->participants, $this->hat);
Metrics::increment('participants', count($this->participants));
event(new DrawDone($draw));
}
protected function createDraw($title, $body, $dataExpiration): Draw
{
$draw = new Draw();
$draw->expires_at = $dataExpiration;
$draw->mail_title = $mailContent['title'];
$draw->mail_body = $mailContent['body'];
$draw->mail_title = $title;
$draw->mail_body = $body;
$draw->save();
return $draw;
}
protected function createParticipants(Draw $draw, array $participants, $hat): void
{
$draw->participants = collect();
foreach ($participants as $idx => $santa) {
$participant = new Participant();
......@@ -44,45 +70,11 @@ class DrawHandler
}
foreach ($hat as $santaIdx => $targetIdx) {
$participants[$santaIdx]->exclusions = array_map(function ($participantId) use ($participants) {
$draw->participants[$santaIdx]->exclusions = array_map(function ($participantId) use ($participants) {
return $participants[$participantId]->id;
}, $participants[$santaIdx]->exclusions);
$participants[$santaIdx]->target()->save($participants[$targetIdx]);
$participants[$santaIdx]->save();
}
$this->informOrganizer($draw);
$this->informParticipants($draw);
}
public function informOrganizer(Draw $draw): void
{
SendMail::dispatch($draw->organizer, new OrganizerRecap($draw));
$draw->participants->each(function (&$participant) {
$participant->exclusions[] = $participant->target->id;
});
try {
// Check if there's a solution with the previous exclusions + the actual target
Solver::one($draw->participants->all(), $draw->participants->pluck('exclusions', 'id')->all());
} catch (SolverException $e) {
// If not, reset all the exclusions
$draw->participants->each(function (&$participant) {
$participant->exclusions = [];
});
}
SendMail::dispatch($draw->organizer, new OrganizerFinalRecap($draw))
->delay($draw->expires_at->addDays(2));
}
public function informParticipants(Draw $draw): void
{
foreach ($draw->participants as $participant) {
Metrics::increment('email');
SendMail::dispatch($participant, new TargetDrawn($participant));
$draw->participants[$santaIdx]->target()->save($participants[$targetIdx]);
$draw->participants[$santaIdx]->save();
}
}
}
......@@ -76,6 +76,6 @@
"@php artisan key:generate --ansi"
],
"check-style": "php-cs-fixer fix --dry-run --allow-risky=yes --diff",
"fix-style": "php-cs-fixer fix"
"fix-style": "php-cs-fixer fix --allow-risky=yes"
}
}
......@@ -218,6 +218,7 @@ return [
'Cookie' => Illuminate\Support\Facades\Cookie::class,
'Crypt' => Illuminate\Support\Facades\Crypt::class,
'DB' => Illuminate\Support\Facades\DB::class,
'DrawHandler' => Facades\App\Services\DrawHandler::class,
'Eloquent' => Illuminate\Database\Eloquent\Model::class,
'Event' => Illuminate\Support\Facades\Event::class,
'File' => Illuminate\Support\Facades\File::class,
......
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
......@@ -2,161 +2,51 @@
namespace Tests\Feature;
use App\Draw;
use App\Jobs\SendMail;
use App\Participant;
use Metrics;
use Queue;
use DrawHandler;
class RequestTest extends RequestCase
{
use \Illuminate\Foundation\Testing\DatabaseMigrations;
use \Illuminate\Foundation\Testing\DatabaseTransactions;
protected function validateForm($parameters)
public function test_service_format(): void
{
return $this->ajaxPost('/', array_merge([
'data-expiration' => date('Y-m-d', strtotime('+2 days')),
], $parameters));
}
public function testInvalid(): void
{
Queue::fake();
Queue::assertNotPushed(SendMail::class);
Metrics::shouldReceive('increment')
->never();
$this->assertEquals(0, Draw::count());
$this->assertEquals(0, Participant::count());
$response = $this->validateForm([
'participants' => [
[
'name' => 'toto',
'email' => 'test@test.com',
'exclusions' => ['2'],
],
[
'name' => 'tata',
'email' => 'test3@test.com',
'exclusions' => ['0', '2'],
],
[
'name' => 'tutu',
'email' => 'test2@test.com',
'exclusions' => ['1'],
],
],
'title' => 'test mail title',
'content-email' => 'test mail {SANTA} => {TARGET}',
]);
$response
->assertStatus(500)
->assertJson([
'error' => 'Aucune solution possible',
]);
$mock = DrawHandler::partialMock();
$this->assertEquals(0, Draw::count());
$this->assertEquals(0, Participant::count());
}
public function testClassic(): void
{
Metrics::shouldReceive('increment')
$mock->shouldReceive('toParticipants')
->once()
->with('draws')
->andReturn(true);
Metrics::shouldReceive('increment')
->with([
['name' => 'toto', 'email' => 'test@test.com', 'exclusions' => []],
['name' => 'tata', 'email' => 'test3@test.com', 'exclusions' => [1, 2]],
['name' => 'tutu', 'email' => 'test2@test.com', 'exclusions' => [0]],
])
->andReturnSelf();
$mock->shouldReceive('sendMail')
->once()
->with('participants', 3)
->andReturn(true);
Metrics::shouldReceive('increment')
->times(3)
->with('email')
->andReturn(true);
Queue::fake();
Queue::assertNotPushed(SendMail::class);
// TODO: also test mail content
$this->assertEquals(0, Draw::count());
$this->assertEquals(0, Participant::count());
$response = $this->validateForm([
$response = $this->ajaxPost('/', [
'participants' => [
[
'name' => 'toto',
'email' => 'test@test.com',
'exclusions' => ['2'],
'exclusions' => [],
],
[
'name' => 'tata',
'email' => 'test3@test.com',
'exclusions' => ['0'],
'exclusions' => ['1', '2'],
],
[
'name' => 'tutu',
'email' => 'test2@test.com',
'exclusions' => ['1'],
'exclusions' => ['0'],
],
],
'title' => 'test mail {SANTA} => {TARGET} title',
'content-email' => 'test mail {SANTA} => {TARGET} body',
'title' => 'test mail title',
'content-email' => 'test mail {SANTA} => {TARGET}',
'data-expiration' => date('Y-m-d', strtotime('+2 days')),
]);
$response
->assertStatus(200)
->assertJson([
'message' => 'Envoyé avec succès !',
]);
Queue::assertPushed(SendMail::class, function ($job) {
return $job->getMailable() instanceof \App\Mail\OrganizerRecap &&
$job->getRecipient()->address === 'test@test.com';
});
$title = $body = null;
Queue::assertPushed(SendMail::class, function ($job) use (&$title, &$body) {
if (
$job->getMailable() instanceof \App\Mail\TargetDrawn &&
$job->getRecipient()->address === 'test@test.com'
) {
$title = $job->getMailable()->subject;
//$m = $job->getMailable()->build();
//$body = view($m->view, $m->buildViewData())->render();
return true;
}
return false;
});
$this->assertStringContainsString('test mail toto => tata title', html_entity_decode($title));
//$this->assertStringContainsString('test mail toto => tata body', html_entity_decode($body));
$body = null;
Queue::assertPushed(SendMail::class, function ($job) use (&$title, &$body) {
if (
$job->getMailable() instanceof \App\Mail\TargetDrawn &&
$job->getRecipient()->address === 'test2@test.com'
) {
//$m = $job->getMailable()->build();
//$body = view($m->view, $m->buildViewData())->render();
return true;
}
return false;
});
//$this->assertStringContainsString('test mail tutu => toto', html_entity_decode($body));
$this->assertEquals(1, Draw::count());
$this->assertEquals(3, Participant::count());
}
}
<?php
namespace Tests\Unit;
use App\Draw;
use App\Exceptions\SolverException;
use App\Jobs\SendMail;
use App\Mail\OrganizerRecap;
use App\Mail\TargetDrawn;
use App\Participant;
use DrawHandler;
use Exception;
use Metrics;
use Queue;
use Tests\TestCase;
class DrawHandlerTest extends TestCase
{
use \Illuminate\Foundation\Testing\DatabaseMigrations;
use \Illuminate\Foundation\Testing\DatabaseTransactions;
public function test_invalid_case(): void
{
Queue::fake();
Queue::assertNotPushed(SendMail::class);
Metrics::shouldReceive('increment')
->never();
$this->assertEquals(0, Draw::count());
$this->assertEquals(0, Participant::count());
try {
DrawHandler::toParticipants([
['name' => 'toto', 'email' => 'test@test.com', 'exclusions' => [2]],
['name' => 'tata', 'email' => 'test3@test.com', 'exclusions' => [0, 2]],
['name' => 'tutu', 'email' => 'test2@test.com', 'exclusions' => [1]],
]);
$this->fail('Expected Exception');
} catch (Exception $e) {
$this->assertEquals(get_class($e), SolverException::class);
}
$this->assertEquals(0, Draw::count());
$this->assertEquals(0, Participant::count());
}
public function test_classic(): void
{
Metrics::shouldReceive('increment')
->once()
->with('draws')
->andReturn(true);
Metrics::shouldReceive('increment')
->once()
->with('participants', 3)
->andReturn(true);
Metrics::shouldReceive('increment')
->times(3)
->with('email')
->andReturn(true);
Queue::fake();
$this->assertEquals(0, Draw::count());
$this->assertEquals(0, Participant::count());
DrawHandler::toParticipants([
['name' => 'toto', 'email' => 'test@test.com', 'exclusions' => [2]],
['name' => 'tata', 'email' => 'test3@test.com', 'exclusions' => [0]],
['name' => 'tutu', 'email' => 'test2@test.com', 'exclusions' => [1]],
])
->expiresAt(date('Y-m-d', strtotime('+2 days')))
->sendMail('test mail {SANTA} => {TARGET} title', 'test mail {SANTA} => {TARGET} body');
Queue::assertPushed(SendMail::class, function ($job) {
return $job->getMailable() instanceof OrganizerRecap &&
$job->getRecipient()->address === 'test@test.com';
});
$title = $body = null;
Queue::assertPushed(SendMail::class, function ($job) use (&$title, &$body) {
if (
$job->getMailable() instanceof TargetDrawn &&
$job->getRecipient()->address === 'test@test.com'
) {
$title = $job->getMailable()->subject;
//$m = $job->getMailable()->build();
//$body = view($m->view, $m->buildViewData())->render();
return true;
}
return false;
});
$this->assertStringContainsString('test mail toto => tata title', html_entity_decode($title));
//$this->assertStringContainsString('test mail toto => tata body', html_entity_decode($body));
$body = null;
Queue::assertPushed(SendMail::class, function ($job) use (&$title, &$body) {
if (
$job->getMailable() instanceof TargetDrawn &&
$job->getRecipient()->address === 'test2@test.com'
) {
//$m = $job->getMailable()->build();
//$body = view($m->view, $m->buildViewData())->render();
return true;
}
return false;
});
//$this->assertStringContainsString('test mail tutu => toto', html_entity_decode($body));
$this->assertEquals(1, Draw::count());
$this->assertEquals(3, Participant::count());
}
}
File mode changed from 100755 to 100644
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment