diff --git a/XMPPHP/XMLStream.php b/XMPPHP/XMLStream.php index ff2c1d5..c9b0bca 100644 --- a/XMPPHP/XMLStream.php +++ b/XMPPHP/XMLStream.php @@ -374,13 +374,10 @@ class XMLStream */ public function event(string $name, ?array $payload = null): void { - $this->log->log("EVENT: $name", Log::LEVEL_DEBUG); + $this->log->log("EVENT: {$name}", Log::LEVEL_DEBUG); foreach ($this->eventhandlers as $handler) { - if ($name == $handler[0]) { - if ($handler[2] === null) { - $handler[2] = $this; - } - $handler[2]->{$handler[1]}($payload); + if ($handler[0] === $name) { + call_user_func_array($handler[1], [&$payload]); } } foreach ($this->until as $key => $until) { @@ -505,12 +502,12 @@ class XMLStream /** * Get next ID * - * @return int + * @return string */ - public function getId(): int + public function getId(): string { - $this->lastid++; - return $this->lastid; + ++$this->lastid; + return (string) $this->lastid; } /** @@ -522,16 +519,45 @@ class XMLStream $this->use_ssl = $use; } + /** + * Compose a proper callable if given legacy syntax + * + * @param callable|string $pointer + * @param object|null|bool $obj + * @return callable + * @throws InvalidArgumentException + */ + protected function ensureHandler($pointer, $obj = false): callable + { + $handler = $pointer; + + if (is_string($pointer)) { + if (is_object($obj)) { + $handler = [$obj, $pointer]; + } elseif (is_null($obj)) { + // Questionable behaviour for backwards compatibility + $handler = [$this, $pointer]; + } + } + + if (!is_callable($handler)) { + throw new \InvalidArgumentException( + 'Cannot compose a proper callable' + ); + } + return $handler; + } + /** * Add ID Handler * * @param int $id - * @param string $pointer - * @param string|null $obj + * @param callable|string $pointer + * @param object|bool|null $obj */ - public function addIdHandler(int $id, string $pointer, ?string $obj = null): void + public function addIdHandler(string $id, $pointer, $obj = null): void { - $this->idhandlers[$id] = [$pointer, $obj]; + $this->idhandlers[$id] = [$this->ensureHandler($pointer, $obj)]; } /** @@ -540,23 +566,23 @@ class XMLStream * @param string $name * @param string $ns * @param string $pointer - * @param string|null $obj + * @param object|bool|null $obj * @param int $depth * - * public function addHandler(string $name, string $ns, string $pointer, ?string $obj = null, int $depth = 1): void + * public function addHandler(string $name, string $ns, $pointer, $obj = null, int $depth = 1): void * { - * #TODO deprication warning - * $this->nshandlers[] = [$name, $ns, $pointer, $obj, $depth]; + * // TODO deprecation warning + * $this->nshandlers[] = [$name, $ns, $this->ensureHandler($pointer, $obj), $depth]; * }*/ /** * Add XPath Handler * * @param string $xpath - * @param string $pointer - * @param string|null $obj + * @param callable|string $pointer + * @param object|bool|null $obj */ - public function addXPathHandler(string $xpath, string $pointer, ?string $obj = null): void + public function addXPathHandler(string $xpath, $pointer, $obj = null): void { if (preg_match_all('/\/?(\{[^\}]+\})?[^\/]+/', $xpath, $regs)) { $tag = $regs[0]; @@ -569,19 +595,20 @@ class XMLStream preg_match('/(\{([^\}]+)\})?(.*)/', $t, $regs); $xpath_array[] = [$regs[2], $regs[3]]; } - $this->xpathhandlers[] = [$xpath_array, $pointer, $obj]; + + $this->xpathhandlers[] = [$xpath_array, $this->ensureHandler($pointer, $obj)]; } /** * Add Event Handler * * @param string $name - * @param string $pointer - * @param object $obj + * @param callable|string $pointer + * @param object|bool|null $obj */ - public function addEventHandler(string $name, string $pointer, object $obj) + public function addEventHandler(string $name, $pointer, $obj = null): void { - $this->eventhandlers[] = [$name, $pointer, $obj]; + $this->eventhandlers[] = [$name, $this->ensureHandler($pointer, $obj)]; } /** @@ -715,12 +742,8 @@ class XMLStream break; } } - if ($searchxml !== null) { - if ($handler[2] === null) { - $handler[2] = $this; - } - $this->log->log("Calling {$handler[1]}", Log::LEVEL_DEBUG); - $handler[2]->{$handler[1]}($this->xmlobj[2]); + if (!is_null($searchxml)) { + call_user_func_array($handler[1], [&$this->xmlobj[2]]); } } } @@ -731,21 +754,25 @@ class XMLStream } elseif (is_array($this->xmlobj) and array_key_exists(2, $this->xmlobj)) { $searchxml = $this->xmlobj[2]; } - if ($searchxml !== null and $searchxml->name == $handler[0] and ($searchxml->ns == $handler[1] or (!$handler[1] and $searchxml->ns == $this->default_ns))) { - if ($handler[3] === null) { - $handler[3] = $this; - } - $this->log->log("Calling {$handler[2]}", Log::LEVEL_DEBUG); - $handler[3]->{$handler[2]}($this->xmlobj[2]); + if ( + !is_null($searchxml) + && $searchxml->name === $handler[0] + && ( + (!$handler[1] && $searchxml->ns === $this->default_ns) + || $searchxml->ns === $handler[1] + ) + ) { + call_user_func_array($handler[2], [&$this->xmlobj[2]]); } } foreach ($this->idhandlers as $id => $handler) { - if (array_key_exists('id', $this->xmlobj[2]->attrs) and $this->xmlobj[2]->attrs['id'] == $id) { - if ($handler[1] === null) { - $handler[1] = $this; - } - $handler[1]->{$handler[0]}($this->xmlobj[2]); - #id handlers are only used once + if ( + array_key_exists(2, $this->xmlobj) + && array_key_exists('id', $this->xmlobj[2]->attrs) + && $this->xmlobj[2]->attrs['id'] === (string) $id + ) { + call_user_func_array($handler[0], [&$this->xmlobj[2]]); + // id handlers are only used once unset($this->idhandlers[$id]); break; } diff --git a/XMPPHP/XMPP.php b/XMPPHP/XMPP.php index 3e12574..284f30d 100644 --- a/XMPPHP/XMPP.php +++ b/XMPPHP/XMPP.php @@ -135,13 +135,34 @@ class XMPP extends XMLStream $this->stream_end = ''; $this->default_ns = 'jabber:client'; - $this->addXPathHandler('{http://etherx.jabber.org/streams}features', 'features_handler'); - $this->addXPathHandler('{urn:ietf:params:xml:ns:xmpp-sasl}success', 'sasl_success_handler'); - $this->addXPathHandler('{urn:ietf:params:xml:ns:xmpp-sasl}failure', 'sasl_failure_handler'); - $this->addXPathHandler('{urn:ietf:params:xml:ns:xmpp-tls}proceed', 'tls_proceed_handler'); - $this->addXPathHandler('{jabber:client}message', 'message_handler'); - $this->addXPathHandler('{jabber:client}presence', 'presence_handler'); - $this->addXPathHandler('iq/{jabber:iq:roster}query', 'roster_iq_handler'); + $this->addXPathHandler( + '{http://etherx.jabber.org/streams}features', + [$this, 'features_handler'] + ); + $this->addXPathHandler( + '{urn:ietf:params:xml:ns:xmpp-sasl}success', + [$this, 'sasl_success_handler'] + ); + $this->addXPathHandler( + '{urn:ietf:params:xml:ns:xmpp-sasl}failure', + [$this, 'sasl_failure_handler'] + ); + $this->addXPathHandler( + '{urn:ietf:params:xml:ns:xmpp-tls}proceed', + [$this, 'tls_proceed_handler'] + ); + $this->addXPathHandler( + '{jabber:client}message', + [$this, 'message_handler'] + ); + $this->addXPathHandler( + '{jabber:client}presence', + [$this, 'presence_handler'] + ); + $this->addXPathHandler( + 'iq/{jabber:iq:roster}query', + [$this, 'roster_iq_handler'] + ); } /** @@ -326,8 +347,8 @@ class XMPP extends XMLStream */ public function getVCard(?string $jid = null): void { - $id = $this->getID(); - $this->addIdHandler($id, 'vcard_get_handler'); + $id = $this->getId(); + $this->addIdHandler($id, [$this, 'vcard_get_handler']); if ($jid) { $this->send(""); } else { @@ -347,7 +368,7 @@ class XMPP extends XMLStream $this->send(""); } elseif ($xml->hasSub('bind') and $this->authed) { $id = $this->getId(); - $this->addIdHandler($id, 'resource_bind_handler'); + $this->addIdHandler($id, [$this, 'resource_bind_handler']); $this->send("{$this->resource}"); } else { $this->log->log("Attempting Auth..."); @@ -401,7 +422,7 @@ class XMPP extends XMLStream $this->jid = $jidarray[0]; } $id = $this->getId(); - $this->addIdHandler($id, 'session_start_handler'); + $this->addIdHandler($id, [$this, 'session_start_handler']); $this->send(""); }