1<?php 2 3/** 4 * Hoa 5 * 6 * 7 * @license 8 * 9 * New BSD License 10 * 11 * Copyright © 2007-2017, Hoa community. All rights reserved. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions are met: 15 * * Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * * Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * * Neither the name of the Hoa nor the names of its contributors may be 21 * used to endorse or promote products derived from this software without 22 * specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE 28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 34 * POSSIBILITY OF SUCH DAMAGE. 35 */ 36 37namespace Hoa\Event; 38 39/** 40 * Class \Hoa\Event\Listener. 41 * 42 * A contrario of events, listeners are synchronous, identified at use and 43 * useful for close interactions between one or some components. 44 * 45 * @copyright Copyright © 2007-2017 Hoa community 46 * @license New BSD License 47 */ 48class Listener 49{ 50 /** 51 * Source of listener (for Bucket). 52 * 53 * @var \Hoa\Event\Listenable 54 */ 55 protected $_source = null; 56 57 /** 58 * All listener IDs and associated listeners. 59 * 60 * @var array 61 */ 62 protected $_callables = []; 63 64 65 66 /** 67 * Build a listener. 68 * 69 * @param \Hoa\Event\Listenable $source Source (for Bucket). 70 * @param array $ids Accepted ID. 71 */ 72 public function __construct(Listenable $source, array $ids) 73 { 74 $this->_source = $source; 75 $this->addIds($ids); 76 77 return; 78 } 79 80 /** 81 * Add acceptable ID (or reset). 82 * 83 * @param array $ids Accepted ID. 84 * @return void 85 */ 86 public function addIds(array $ids) 87 { 88 foreach ($ids as $id) { 89 $this->_callables[$id] = []; 90 } 91 92 return; 93 } 94 95 /** 96 * Attach a callable to a listenable component. 97 * 98 * @param string $listenerId Listener ID. 99 * @param mixed $callable Callable. 100 * @return \Hoa\Event\Listener 101 * @throws \Hoa\Event\Exception 102 */ 103 public function attach($listenerId, $callable) 104 { 105 if (false === $this->listenerExists($listenerId)) { 106 throw new Exception( 107 'Cannot listen %s because it is not defined.', 108 0, 109 $listenerId 110 ); 111 } 112 113 $callable = xcallable($callable); 114 $this->_callables[$listenerId][$callable->getHash()] = $callable; 115 116 return $this; 117 } 118 119 /** 120 * Detach a callable from a listenable component. 121 * 122 * @param string $listenerId Listener ID. 123 * @param mixed $callable Callable. 124 * @return \Hoa\Event\Listener 125 */ 126 public function detach($listenerId, $callable) 127 { 128 unset($this->_callables[$listenerId][xcallable($callable)->getHash()]); 129 130 return $this; 131 } 132 133 /** 134 * Detach all callables from a listenable component. 135 * 136 * @param string $listenerId Listener ID. 137 * @return \Hoa\Event\Listener 138 */ 139 public function detachAll($listenerId) 140 { 141 unset($this->_callables[$listenerId]); 142 143 return $this; 144 } 145 146 /** 147 * Check if a listener exists. 148 * 149 * @param string $listenerId Listener ID. 150 * @return bool 151 */ 152 public function listenerExists($listenerId) 153 { 154 return array_key_exists($listenerId, $this->_callables); 155 } 156 157 /** 158 * Send/fire a bucket to a listener. 159 * 160 * @param string $listenerId Listener ID. 161 * @param \Hoa\Event\Bucket $data Data. 162 * @return array 163 * @throws \Hoa\Event\Exception 164 */ 165 public function fire($listenerId, Bucket $data) 166 { 167 if (false === $this->listenerExists($listenerId)) { 168 throw new Exception( 169 'Cannot fire on %s because it is not defined.', 170 1, 171 $listenerId 172 ); 173 } 174 175 $data->setSource($this->_source); 176 $out = []; 177 178 foreach ($this->_callables[$listenerId] as $callable) { 179 $out[] = $callable($data); 180 } 181 182 return $out; 183 } 184} 185