1<?php 2 3/** 4 * Copyright 2014 Fabian Grutschus. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without modification, 7 * are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright notice, this 10 * list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright notice, 13 * this list of conditions and the following disclaimer in the documentation 14 * and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 * 27 * The views and conclusions contained in the software and documentation are those 28 * of the authors and should not be interpreted as representing official policies, 29 * either expressed or implied, of the copyright holders. 30 * 31 * @author Fabian Grutschus <f.grutschus@lubyte.de> 32 * @copyright 2014 Fabian Grutschus. All rights reserved. 33 * @license BSD 34 * @link http://github.com/fabiang/xmpp 35 */ 36 37namespace Fabiang\Xmpp\Event; 38 39use Fabiang\Xmpp\Exception\InvalidArgumentException; 40 41/** 42 * Event manager. 43 * 44 * The EventManager holds and triggers events. 45 * 46 * @package Xmpp\Event 47 */ 48class EventManager implements EventManagerInterface 49{ 50 51 const WILDCARD = '*'; 52 53 /** 54 * Attached events. 55 * 56 * @var array 57 */ 58 protected $events = array(self::WILDCARD => array()); 59 60 /** 61 * Event object. 62 * 63 * @var EventInterface 64 */ 65 protected $eventObject; 66 67 /** 68 * Constructor sets default event object. 69 * 70 * @param EventInterface $eventObject Event object 71 */ 72 public function __construct(EventInterface $eventObject = null) 73 { 74 if (null === $eventObject) { 75 $eventObject = new Event; 76 } 77 78 $this->eventObject = $eventObject; 79 } 80 81 /** 82 * {@inheritDoc} 83 */ 84 public function attach($event, $callback) 85 { 86 if (!is_callable($callback, true)) { 87 throw new InvalidArgumentException( 88 'Second argument of "' . __CLASS__ . '"::attach must be a valid callback' 89 ); 90 } 91 92 if (!isset($this->events[$event])) { 93 $this->events[$event] = array(); 94 } 95 96 if (!in_array($callback, $this->events[$event], true)) { 97 $this->events[$event][] = $callback; 98 } 99 } 100 101 /** 102 * {@inheritDoc} 103 */ 104 public function trigger($event, $caller, array $parameters) 105 { 106 if (empty($this->events[$event]) && empty($this->events[self::WILDCARD])) { 107 return; 108 } 109 110 $events = array(); 111 if (!empty($this->events[$event])) { 112 $events = $this->events[$event]; 113 } 114 115 $callbacks = array_merge($events, $this->events[self::WILDCARD]); 116 $previous = array(); 117 118 $eventObject = clone $this->getEventObject(); 119 $eventObject->setName($event); 120 $eventObject->setTarget($caller); 121 $eventObject->setParameters($parameters); 122 123 do { 124 $current = array_shift($callbacks); 125 126 call_user_func($current, $eventObject); 127 128 $previous[] = $current; 129 $eventObject = clone $eventObject; 130 $eventObject->setEventStack($previous); 131 } while (count($callbacks) > 0); 132 } 133 134 /** 135 * {@inheritDoc} 136 */ 137 public function getEventObject() 138 { 139 return $this->eventObject; 140 } 141 142 /** 143 * {@inheritDoc} 144 */ 145 public function setEventObject(EventInterface $eventObject) 146 { 147 $this->eventObject = $eventObject; 148 return $this; 149 } 150 151 /** 152 * Return list of events. 153 * 154 * @return array 155 */ 156 public function getEventList() 157 { 158 return $this->events; 159 } 160} 161