@@ -23,6 +23,9 @@ trait OffersHooks
23
23
/** @var \SplObjectStorage|array<\Closure> */
24
24
private $ messageReceivedEventHandlers ;
25
25
26
+ /** @var \SplObjectStorage|array<\Closure> */
27
+ private $ connectedEventHandlers ;
28
+
26
29
/**
27
30
* Needs to be called in order to initialize the trait.
28
31
*
@@ -33,6 +36,7 @@ protected function initializeEventHandlers(): void
33
36
$ this ->loopEventHandlers = new \SplObjectStorage ();
34
37
$ this ->publishEventHandlers = new \SplObjectStorage ();
35
38
$ this ->messageReceivedEventHandlers = new \SplObjectStorage ();
39
+ $ this ->connectedEventHandlers = new \SplObjectStorage ();
36
40
}
37
41
38
42
/**
@@ -266,4 +270,77 @@ private function runMessageReceivedEventHandlers(string $topic, string $message,
266
270
}
267
271
}
268
272
}
273
+
274
+ /**
275
+ * Registers an event handler which is called when the client established a connection to the broker.
276
+ * This also includes manual reconnects as well as auto-reconnects by the client itself.
277
+ *
278
+ * The event handler is passed the MQTT client as first argument,
279
+ * followed by a flag which indicates whether an auto-reconnect occurred as second argument.
280
+ *
281
+ * Example:
282
+ * ```php
283
+ * $mqtt->registerConnectedEventHandler(function (
284
+ * MqttClient $mqtt,
285
+ * bool $isAutoReconnect
286
+ * ) use ($logger) {
287
+ * if ($isAutoReconnect) {
288
+ * $logger->info("Client successfully auto-reconnected to the broker.);
289
+ * } else {
290
+ * $logger->info("Client successfully connected to the broker.");
291
+ * }
292
+ * });
293
+ * ```
294
+ *
295
+ * Multiple event handlers can be registered at the same time.
296
+ *
297
+ * @param \Closure $callback
298
+ * @return MqttClient
299
+ */
300
+ public function registerConnectedEventHandler (\Closure $ callback ): MqttClient
301
+ {
302
+ $ this ->connectedEventHandlers ->attach ($ callback );
303
+
304
+ /** @var MqttClient $this */
305
+ return $ this ;
306
+ }
307
+
308
+ /**
309
+ * Unregisters a connected event handler which prevents it from being called in the future.
310
+ *
311
+ * This does not affect other registered event handlers. It is possible
312
+ * to unregister all registered event handlers by passing null as callback.
313
+ *
314
+ * @param \Closure|null $callback
315
+ * @return MqttClient
316
+ */
317
+ public function unregisterConnectedEventHandler (\Closure $ callback = null ): MqttClient
318
+ {
319
+ if ($ callback === null ) {
320
+ $ this ->connectedEventHandlers ->removeAll ($ this ->connectedEventHandlers );
321
+ } else {
322
+ $ this ->connectedEventHandlers ->detach ($ callback );
323
+ }
324
+
325
+ /** @var MqttClient $this */
326
+ return $ this ;
327
+ }
328
+
329
+ /**
330
+ * Runs all the registered connected event handlers.
331
+ * Each event handler is executed in a try-catch block to avoid spilling exceptions.
332
+ *
333
+ * @param bool $isAutoReconnect
334
+ * @return void
335
+ */
336
+ private function runConnectedEventHandlers (bool $ isAutoReconnect ): void
337
+ {
338
+ foreach ($ this ->connectedEventHandlers as $ handler ) {
339
+ try {
340
+ call_user_func ($ handler , $ this , $ isAutoReconnect );
341
+ } catch (\Throwable $ e ) {
342
+ $ this ->logger ->error ('Connected hook callback threw exception. ' , ['exception ' => $ e ]);
343
+ }
344
+ }
345
+ }
269
346
}
0 commit comments