Skip to content

Commit

Permalink
Subject : Fix notification erased by another
Browse files Browse the repository at this point in the history
Remove setter and method notifyAction
Add the new method addNotification and the property notifyHeap.

Fix the case when a notify is send to observer, if one of the an observer re-send a notification immediatly, so others observer can not access to the first notification infos (action and context).
  • Loading branch information
bulton-fr committed Jul 5, 2017
1 parent a13d274 commit d95e44e
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 63 deletions.
4 changes: 2 additions & 2 deletions install/class/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,10 @@ public function run()
$notifyAction = $action[1];
}

$this->notifyAction('bfw_modules_install_run_'.$notifyAction);
$this->addNotification('bfw_modules_install_run_'.$notifyAction);
}

$this->notifyAction('bfw_modules_install_finish');
$this->addNotification('bfw_modules_install_finish');
}

/**
Expand Down
8 changes: 4 additions & 4 deletions src/class/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -382,10 +382,10 @@ public function run()
$notifyAction = $action[1];
}

$this->notifyAction('apprun_'.$notifyAction);
$this->addNotification('apprun_'.$notifyAction);
}

$this->notifyAction('bfw_run_finish');
$this->addNotification('bfw_run_finish');
}

/**
Expand Down Expand Up @@ -497,7 +497,7 @@ protected function loadAllAppModules()
*/
protected function loadModule($moduleName)
{
$this->notifyAction('load_module_'.$moduleName);
$this->addNotification('load_module_'.$moduleName);
$this->modules->getModule($moduleName)->runModule();
}

Expand Down Expand Up @@ -534,7 +534,7 @@ protected function runCliFile()
require_once(CLI_DIR.$file.'.php');
};

$this->notifyAction('run_cli_file');
$this->addNotification('run_cli_file');
$fctRunCliFile();
}
}
73 changes: 41 additions & 32 deletions src/class/Subjects.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,17 @@ class Subjects implements SplSubject
protected $observers = [];

/**
* @var string $action The action to send to observers
* @var \stdClass[] $notifyHeap List of notify to send
*/
protected $notifyHeap = [];

/**
* @var string $action The current action to send to observers
*/
protected $action = '';

/**
* @var mixed $context The context to send to observers
* @var mixed $context The current context to send to observers
*/
protected $context = null;

Expand All @@ -45,19 +50,6 @@ public function getAction()
return $this->action;
}

/**
* Define the action
*
* @param string $action The new action
*
* @return \BFW\Subjects The current instance of this class
*/
public function setAction($action)
{
$this->action = $action;
return $this;
}

/**
* Return the context
*
Expand All @@ -67,19 +59,6 @@ public function getContext()
{
return $this->context;
}

/**
* Define the context
*
* @param mixed $context The new context
*
* @return \BFW\Subjects The current instance of this class
*/
public function setContext($context)
{
$this->context = $context;
return $this;
}

/**
* Attach a new observer to the list
Expand Down Expand Up @@ -123,21 +102,51 @@ public function notify()
foreach ($this->observers as $observer) {
$observer->update($this);
}

return $this;
}

public function readNotifyHeap()
{
foreach ($this->notifyHeap as $notifyIndex => $notifyDatas) {
$this->action = $notifyDatas->action;
$this->context = $notifyDatas->context;

$this->notify();

//Remove the current notification from list
unset($this->notifyHeap[$notifyIndex]);
}

//Some new notifications has been added during the loop
if (count($this->notifyHeap) > 0) {
$this->readNotifyHeap();
}

return $this;
}

/**
* Send a notification to all observers with an action
* Add a new notification to the list of notification to send.
* If there is only one notification into the list, it will be send now.
* Else, a notification is currently sent, so we wait it finish and the
* current notification will be sent.
*
* @param string $action The action to send
* @param notification $context (default null) The context to send
*
* @return \BFW\Subjects The current instance of this class
*/
public function notifyAction($action)
public function addNotification($action, $context = null)
{
$this->action = $action;
$this->notify();
$this->notifyHeap[] = (object) [
'action' => $action,
'context' => $context
];

if (count($this->notifyHeap) === 1) {
$this->readNotifyHeap();
}

return $this;
}
Expand Down
96 changes: 71 additions & 25 deletions test/unit/src/class/Subjects.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class Subjects extends atoum
*/
public function beforeTestMethod($testMethod)
{
$this->class = new \BFW\Subjects();
$this->class = new \BFW\Subjects;
}

/**
Expand Down Expand Up @@ -64,34 +64,41 @@ public function testDetach()
}

/**
* Test method for getAction() and setAction()
* Test method for getAction()
*
* @return void
*/
public function testGetAndSetAction()
public function testGetAction()
{
$this->assert('test Subjects getAction and setAction')
$this->assert('test Subjects getAction')
->string($this->class->getAction())
->isEmpty()
->given($this->class->setAction('unit_test'))
->if($this->class->addNotification('unit_test'))
->then
->string($this->class->getAction())
->isEqualTo('unit_test');
}

/**
* Test method for getContext() and setContext()
* Test method for getContext()
*
* @return void
*/
public function testGetAndSetContext()
public function testGetContext()
{
$this->assert('test Subjects getContext and setContext')
->variable($this->class->getContext())
->isNull()
->given($this->class->setContext([
'test' => 'unit',
'lib' => 'atoum'
]))
->if($this->class->addNotification(
'unit_test',
[
'test' => 'unit',
'lib' => 'atoum'
]
))
->then
->string($this->class->getAction())
->isEqualTo('unit_test')
->array($this->class->getContext())
->isEqualTo([
'test' => 'unit',
Expand All @@ -112,27 +119,66 @@ public function testNotify()
->given($class = $this->class)
->output(function() use ($class) {
$class->notify();
})->isEqualTo("\n")
->if($this->class->setAction('unit_test'))
->then
->output(function() use ($class) {
$class->notify();
})->isEqualTo('unit_test'."\n");
})->isEqualTo("\n");
}

/**
* Test method for notifyAction()
* Test method for addNotification()
*
* @return void
*/
public function testNotifyAction()
public function testAddNotification()
{
$this->assert('test notifyAction')
->given($observer = new MockObserver)
->given($this->class->attach($observer))
->given($class = $this->class)
->output(function() use ($class) {
$class->notifyAction('unit_test');
$observer = [
new MockObserver,
new \mock\BFW\test\unit\mocks\Observer //Atoum mock
];

//Modify the method update to the second observer to test the case
//Where update send a new notification.
$this->calling($observer[1])->update = function(\SplSubject $subject) {
if ($subject->getAction() === 'unit_test') {
$subject->addNotification('unit_test2');
}

echo $subject->getAction()."\n";
};

$this->assert('test addNotification with one observer')
->given($this->class->attach($observer[0]))
->output(function() {
$this->class->addNotification('unit_test');
})->isEqualTo('unit_test'."\n");

$this->assert(
'test addNotification with two observer. '
.'Re-send notification into the second.'
)
->given($this->class->attach($observer[1]))
->output(function() {
$this->class->addNotification('unit_test');
})->isEqualTo(
'unit_test'."\n"
.'unit_test'."\n"
.'unit_test2'."\n"
.'unit_test2'."\n"
);

$this->assert(
'test addNotification with two observer. '
.'Re-send notification into the first.'
)
->given($this->class->detach($observer[0]))
->given($this->class->detach($observer[1]))
->given($this->class->attach($observer[1]))
->given($this->class->attach($observer[0]))
->output(function() {
$this->class->addNotification('unit_test');
})->isEqualTo(
'unit_test'."\n"
.'unit_test'."\n"
.'unit_test2'."\n"
.'unit_test2'."\n"
);
}
}

0 comments on commit d95e44e

Please sign in to comment.