private static function execute($fire, &$list) { $omit = false; for ($i = 0; $i < sizeof($list['list']); $i++) { //Подписка на ходу $handler =& $list['list'][$i]; if (!empty($handler['executed'][$fire['objid']])) { continue; } if (!is_null($handler['obj']) && $handler['objid'] !== $fire['objid']) { continue; } else { //Объекта у подписки не указан //fire с объктом, подписка без объекта //подписка должна выполниться для всех объектов fire. Проходим дальше } if (empty($handler['keystik'])) { Event::keystik($handler); } $iskeys = array_diff($handler['keystik'], $list['readykeys'][$fire['objid']]); //Проверили выполнены ли все существующие ключи if (sizeof($iskeys) && (sizeof($iskeys) != 1 || is_null($handler['key']) || !in_array($handler['key'], $handler['keys']))) { $omit = array('keys' => $iskeys, 'handler' => $handler, 'fire' => $fire); continue; //Найден неудовлетворённый ключ.. может быть выход из цикла и на ислкючение } if (empty($list['readyobj'][$fire['objid']][$handler['key']])) { $list['readyobj'][$fire['objid']][$handler['key']] = 0; } $list['readyobj'][$fire['objid']][$handler['key']]++; if (static::hv($handler['key'])) { //Если есть ключ if (!in_array($handler['key'], $list['readykeys'][$fire['objid']])) { //И этого ключа ещё не было //Если выполнено по объекту столько же сколько всего обработчиков if ($list['readyobj'][$fire['objid']][$handler['key']] === sizeof($list['keys'][$handler['key']])) { $list['readykeys'][$fire['objid']][] = $handler['key']; } } } $handler['executed'][$fire['objid']] = true; $moment = array("fire" => $fire, "handler" => $handler, "parent" => static::$moment, "list" => $list, "i" => $i); static::$moment = $moment; $r = $handler['callback']($fire['obj']); static::$moment = $moment['parent']; if (!static::is($r)) { return $r; } $r = static::execute($fire, $list); return $r; } if ($omit) { echo '<pre>'; unset($fire['obj']); print_r($omit); echo '<hr>'; print_r($list); throw new \Exception('Рекурсивная зависимость подписчиков. ' . implode(',', $omit['keys'])); } }
public static function fire($name, &$obj = null) { /** * Уникальность очереди событий определяется именем события содержащей имя класса события. * Все подписки хранятся в классе и объект не меняется **/ $fire = Event::createFire($name, $obj); $list =& $fire['list']; $data =& $fire['data']; /** * TODO: Реализация is isshow... нужно сбрасывать события **/ if (isset($list['result'][$fire['objid']]) && !is_null($list['result'][$fire['objid']])) { return $list['result'][$fire['objid']]; } if (isset($data['executed']) && $data['executed'] === false) { return true; } //Защита от рекурсий вложенный вызов вернёт true $data['executed'] = false; if (!isset($list['readykeys'][$fire['objid']])) { $list['readykeys'][$fire['objid']] = array(); } if (!isset($list['readyobj'][$fire['objid']])) { $list['readyobj'][$fire['objid']] = array(); } // TODO: проверить обработку несуществующих ключей for ($i = 0, $l = sizeof($list['list']); $i < $l; $i++) { //Подписка на ходу Event::keystik($list['list'][$i]); } $r = Event::execute($fire, $list); if (Event::is($r)) { $r = true; } else { $r = false; } $list['result'][$fire['objid']] = $r; $data['executed'] = true; return $list['result'][$fire['objid']]; }