Skip to content

Commit e2a4770

Browse files
authored
Merge pull request #1 from Maxofil/master
added src files
2 parents 0943b33 + d2b53af commit e2a4770

File tree

7 files changed

+194
-0
lines changed

7 files changed

+194
-0
lines changed

composer.json

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"name": "infinityloop-dev/observer-component",
3+
"description": "Event system for Nette framework's component model.",
4+
"homepage": "https://www.infinityloop.dev/",
5+
"type": "library",
6+
"license": ["MIT"],
7+
"authors": [
8+
{
9+
"name": "Václav Pelíšek",
10+
"homepage": "https://www.peldax.com"
11+
}
12+
],
13+
"require": {
14+
"php": ">=7.4",
15+
"nette/application": "^3.0",
16+
"nette/caching": "^3.0",
17+
"nette/utils": "^3.0"
18+
},
19+
"autoload": {
20+
"psr-4": {
21+
"Infinityloop\\": "src/"
22+
}
23+
}
24+
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
<?php
2+
3+
declare(strict_types = 1);
4+
5+
namespace Infinityloop\ObserverComponent;
6+
7+
final class EventMapper
8+
{
9+
use Nette\SmartObject;
10+
11+
private \Nette\Application\Application $application;
12+
private \Nette\Caching\IStorage $storage;
13+
private ?\Nette\Caching\Cache $eventMap = null;
14+
private bool $debugMode;
15+
16+
public function __construct(
17+
\Nette\Application\Application $application,
18+
\Nette\Caching\IStorage $storage,
19+
bool $debugMode = true
20+
)
21+
{
22+
$this->application = $application;
23+
$this->storage = $storage;
24+
$this->debugMode = $debugMode;
25+
}
26+
27+
public function registerObserver(IObserverComponent $component) : void
28+
{
29+
$componentPath = $component->lookupPath(\Nette\Application\IPresenter::class);
30+
\assert(\is_string($componentPath));
31+
32+
if (!$this->debugMode && $this->isComponentRegistered($componentPath)) {
33+
return;
34+
}
35+
36+
foreach ($component::getObservedEvents() as $eventName) {
37+
\assert(\is_string($eventName) && \class_exists($eventName));
38+
39+
$observerList = $this->getObserverList($eventName);
40+
41+
if (\in_array($componentPath, $observerList, true)) {
42+
continue;
43+
}
44+
45+
$observerList[] = $componentPath;
46+
$this->getEventMap()->save($eventName, $observerList);
47+
48+
$registeredComponents = $this->getEventMap()->load('components') ?? [];
49+
$registeredComponents[] = $componentPath;
50+
$this->getEventMap()->save('components', $registeredComponents);
51+
}
52+
}
53+
54+
public function dispatchEvent(IEvent $event) : void
55+
{
56+
$presenter = $this->application->getPresenter();
57+
\assert($presenter instanceof \Nette\Application\UI\Control);
58+
59+
foreach ($this->getObserverList(\get_class($event)) as $observerPath) {
60+
\assert(\is_string($observerPath));
61+
62+
$observer = $presenter->getComponent($observerPath);
63+
\assert($observer instanceof IObserverComponent);
64+
65+
$observer->observableUpdated($event);
66+
}
67+
}
68+
69+
private function getObserverList(string $eventName) : array
70+
{
71+
return $this->getEventMap()->load($eventName)
72+
?? [];
73+
}
74+
75+
private function isComponentRegistered(string $componentPath) : bool
76+
{
77+
$registeredComponents = $this->getEventMap()->load('components') ?? [];
78+
79+
return \in_array($componentPath, $registeredComponents, true);
80+
}
81+
82+
private function getEventMap() : \Nette\Caching\Cache
83+
{
84+
if (!$this->eventMap instanceof \Nette\Caching\Cache) {
85+
$applicationPath = \ltrim($this->application->getPresenter()->getAction(true), ':');
86+
$this->eventMap = new \Nette\Caching\Cache($this->storage, 'eventMapper-' . $applicationPath);
87+
}
88+
89+
return $this->eventMap;
90+
}
91+
}

src/ObserverComponent/IEvent.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
declare(strict_types = 1);
4+
5+
namespace Infinityloop\ObserverComponent;
6+
7+
interface IEvent
8+
{
9+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
declare(strict_types = 1);
4+
5+
namespace Infinityloop\ObserverComponent;
6+
7+
interface IObservable
8+
{
9+
public function injectEventMapperObservable(EventMapper $eventMapper) : void;
10+
11+
public function notifyObservers(IEvent $event) : void;
12+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
declare(strict_types = 1);
4+
5+
namespace Infinityloop\ObserverComponent;
6+
7+
interface IObserverComponent
8+
{
9+
public static function getObservedEvents() : array;
10+
11+
public function injectEventMapperObserver(EventMapper $eventMapper) : void;
12+
13+
public function observableUpdated(IEvent $event) : void;
14+
15+
public function lookupPath(?string $type = null, bool $throw = true) : ?string;
16+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
declare(strict_types = 1);
4+
5+
namespace Infinityloop\ObserverComponent;
6+
7+
trait TObservable
8+
{
9+
private EventMapper $eventMapper;
10+
11+
final public function injectEventMapperObservable(EventMapper $eventMapper) : void
12+
{
13+
$this->eventMapper = $eventMapper;
14+
}
15+
16+
public function notifyObservers(IEvent $event) : void
17+
{
18+
$this->eventMapper->dispatchEvent($event);
19+
}
20+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
declare(strict_types = 1);
4+
5+
namespace Infinityloop\ObserverComponent;
6+
7+
trait TObserverComponent
8+
{
9+
private EventMapper $eventMapper;
10+
11+
abstract public static function getObservedEvents() : array;
12+
13+
abstract public function observableUpdated(IEvent $event) : void;
14+
15+
final public function injectEventMapperObserver(EventMapper $eventMapper) : void
16+
{
17+
$this->eventMapper = $eventMapper;
18+
$this->onAnchor[] = function (\Nette\ComponentModel\IComponent $parent) : void {
19+
$this->eventMapper->registerObserver($this);
20+
};
21+
}
22+
}

0 commit comments

Comments
 (0)