From 77f64d1870366c1d538f18bfba0e304b0de5de0e Mon Sep 17 00:00:00 2001
From: Bart Jaskulski <bjaskulski@protonmail.com>
Date: Fri, 27 Sep 2024 12:11:59 +0200
Subject: [PATCH] perf: group handlers by hook to improve performance

Signed-off-by: Bart Jaskulski <bjaskulski@protonmail.com>
---
 .../Definition/DefinitionCollection.php       | 44 +++++++++++++++++++
 src/Binding/Loader/ClusteredLoader.php        | 34 ++++++++++++++
 2 files changed, 78 insertions(+)
 create mode 100644 src/Binding/Definition/DefinitionCollection.php
 create mode 100644 src/Binding/Loader/ClusteredLoader.php

diff --git a/src/Binding/Definition/DefinitionCollection.php b/src/Binding/Definition/DefinitionCollection.php
new file mode 100644
index 0000000..ed67b92
--- /dev/null
+++ b/src/Binding/Definition/DefinitionCollection.php
@@ -0,0 +1,44 @@
+<?php
+
+declare(strict_types=1);
+
+namespace WPDesk\Init\Binding\Definition;
+
+use WPDesk\Init\Binding\Definition;
+
+/** @implements Definition<mixed> */
+class DefinitionCollection implements Definition {
+
+	/** @var ?string */
+	private $hook;
+
+	/** @var Definition[] */
+	private $defs;
+
+	/** @var array<string, mixed> */
+	private array $options;
+
+	public function __construct(
+		?string $hook = null,
+		array $options = []
+	) {
+		$this->hook    = $hook;
+		$this->options = $options;
+	}
+
+	public function hook(): ?string {
+		return $this->hook;
+	}
+
+	public function value() {
+		yield from $this->defs;
+	}
+
+	public function add( Definition $def ) {
+		$this->defs[] = $def;
+	}
+
+	public function option( string $name ) {
+		return $this->options[ $name ] ?? null;
+	}
+}
diff --git a/src/Binding/Loader/ClusteredLoader.php b/src/Binding/Loader/ClusteredLoader.php
new file mode 100644
index 0000000..e290fa4
--- /dev/null
+++ b/src/Binding/Loader/ClusteredLoader.php
@@ -0,0 +1,34 @@
+<?php
+declare( strict_types=1 );
+
+namespace WPDesk\Init\Binding\Loader;
+
+use WPDesk\Init\Binding\Definition\DefinitionCollection;
+
+final class ClusteredLoader implements BindingDefinitions {
+
+	private BindingDefinitions $loader;
+
+	public function __construct( BindingDefinitions $loader ) {
+		$this->loader = $loader;
+	}
+
+	public function load(): iterable {
+		$definitions = [];
+		foreach ( $this->loader->load() as $def ) {
+			if ( $def->hook() === null ) {
+				yield $def;
+				continue;
+			}
+
+			if ( ! isset( $definitions[ $def->hook() ] ) ) {
+				$collection                  = new DefinitionCollection( $def->hook() );
+				$definitions[ $def->hook() ] = $collection;
+			}
+
+			$definitions[ $def->hook() ]->add( $def );
+		}
+
+		yield from $definitions;
+	}
+}
-- 
GitLab