6 * @author Michael Wallner <mike@php.net>
11 use hikke\Event\Storage
;
16 * @package hikke\Event
18 class Proxy
implements \SplSubject
, \SplObserver
, \IteratorAggregate
, \Countable
23 private $events = array();
26 * @var \hikke\Event\Storage
30 public function __construct(array $events = ["default"]) {
31 $this->storage
= new Storage
;
32 foreach ((array) $events as $priority => $event) {
33 $this->insert($event, $priority);
38 * Notify all attached observers passing along $origin
39 * @param \SplSubject $origin
41 public function update(\SplSubject
$origin) {
42 $this->notify($origin);
46 * Apply a cvallback ot a specific or all events
47 * @param string $event
48 * @param callable $apply
50 public function apply($event, callable
$apply) {
52 $apply($this->events
[$event]);
54 foreach ($this->storage
as $ev) {
61 * Notify all attached observers to a specific or all events passing alomg $origin
62 * @param object $origin
63 * @param string $event
65 public function notify($origin = null, $event = null) {
66 $this->apply($event, function($ev) use($origin) {
72 * Attach an observer to a specfiv or all events
73 * @param \SplObserver $observer
74 * @param string $event
75 * @param int|float $priority
76 * @return \hikke\Event\Proxy self
78 public function attach(\SplObserver
$observer, $event = null, $priority = 0) {
79 $this->apply($event, function($ev) use($observer, $priority) {
80 $ev->attach($observer, $priority);
86 * Detach an observer from all or a specific event
87 * @param \SplObserver $observer
88 * @param string $event
89 * @return \hikke\Event\Proxy self
91 public function detach(\SplObserver
$observer, $event = null) {
92 $this->apply($event, function($ev) use($observer) {
93 $ev->detach($observer);
99 * Insert a new event type
100 * @param string $name
101 * @param int|float $priority
103 private function insert($name, $priority = 0) {
104 if ($priority instanceof Event
) {
105 /* assignement in the form:
106 * $proxy->foo = new Event("foo", 123);
109 $priority = $event->getPriority();
112 if ($name !== $event->getName()) {
113 throw new \
UnexpectedValueException(
114 sprintf("The event names differ: '%s' <> '%s'",
115 $name, $event->getName()));
117 } elseif (isset($this->events
[$name])) {
118 throw new \
UnexpectedValueException(
119 sprintf("The event name '%s' is already in use", $name));
121 $event = new Event($name);
124 $bucket = $this->storage
->insert($event, $priority);
125 $event->setPriority($bucket->getPriority());
126 $this->events
[$name] = $event;
132 public function __call($method, $args) {
133 $observers = new \SplObjectStorage
;
134 $this->apply(null, function($ev) use($observers) {
135 foreach ($ev as $observer) {
136 if (!$observers->contains($observer)) {
137 $observers->attach($observer);
141 foreach ($observers as $observer) {
142 if (is_callable(array($observer, $method))) {
143 call_user_func_array(array($observer, $method), $args);
151 public function __get($event) {
152 if (!isset($this->events
[$event])) {
153 $this->insert($event);
155 return $this->events
[$event];
161 public function __set($event, $priority) {
162 $this->insert($event, $priority);
168 public function __isset($event) {
169 return isset($this->events
[$event]);
175 public function __unset($event) {
176 if (isset($this->events
[$event])) {
177 $this->storage
->delete($this->events
[$event]);
178 unset($this->events
[$event]);
185 public function getIterator() {
186 return $this->storage
;
192 public function count() {
193 return count($this->storage
);