55namespace WordPress \AiClient \Providers ;
66
77use InvalidArgumentException ;
8+ use WordPress \AiClient \Providers \Contracts \ModelMetadataDirectoryInterface ;
9+ use WordPress \AiClient \Providers \Contracts \ProviderAvailabilityInterface ;
10+ use WordPress \AiClient \Providers \Contracts \ProviderInterface ;
811use WordPress \AiClient \Providers \DTO \ProviderMetadata ;
912use WordPress \AiClient \Providers \DTO \ProviderModelsMetadata ;
13+ use WordPress \AiClient \Providers \Models \Contracts \ModelInterface ;
1014use WordPress \AiClient \Providers \Models \DTO \ModelConfig ;
1115use WordPress \AiClient \Providers \Models \DTO \ModelMetadata ;
1216use WordPress \AiClient \Providers \Models \DTO \ModelRequirements ;
@@ -26,10 +30,6 @@ class AiProviderRegistry
2630 */
2731 private array $ providerClassNames = [];
2832
29- /**
30- * @var array<string, object> Cache of instantiated provider instances.
31- */
32- private array $ providerInstances = [];
3333
3434 /**
3535 * Registers a provider class with the registry.
@@ -47,19 +47,16 @@ public function registerProvider(string $className): void
4747 );
4848 }
4949
50- // TODO: Add interface validation when ProviderInterface is available
51-
52- // Get provider metadata to extract ID
53- $ instance = new $ className ();
54-
55- // Check if provider has metadata method
56- if (!method_exists ($ instance , 'metadata ' )) {
50+ // Validate that class implements ProviderInterface
51+ if (!is_subclass_of ($ className , ProviderInterface::class)) {
5752 throw new InvalidArgumentException (
58- sprintf ('Provider must implement metadata() method : %s ' , $ className )
53+ sprintf ('Provider class must implement %s : %s ' , ProviderInterface::class , $ className )
5954 );
6055 }
6156
62- $ metadata = $ instance ->metadata ();
57+ // Get provider metadata to extract ID (using static method from interface)
58+ /** @var class-string<ProviderInterface> $className */
59+ $ metadata = $ className ::metadata ();
6360
6461 if (!$ metadata instanceof ProviderMetadata) {
6562 throw new InvalidArgumentException (
@@ -115,11 +112,13 @@ public function getProviderClassName(string $id): string
115112 public function isProviderConfigured (string $ idOrClassName ): bool
116113 {
117114 try {
118- $ this ->getProviderInstance ($ idOrClassName );
115+ $ className = $ this ->resolveProviderClassName ($ idOrClassName );
119116
120- // TODO: Call availability() method when ProviderInterface is available
121- // For now, assume configured if we can instantiate without exception
122- return true ;
117+ // Use static method from ProviderInterface
118+ /** @var class-string<ProviderInterface> $className */
119+ $ availability = $ className ::availability ();
120+
121+ return $ availability ->isConfigured ();
123122 } catch (InvalidArgumentException $ e ) {
124123 return false ;
125124 }
@@ -140,17 +139,9 @@ public function findModelsMetadataForSupport(ModelRequirements $modelRequirement
140139 foreach ($ this ->providerClassNames as $ providerId => $ className ) {
141140 $ providerResults = $ this ->findProviderModelsMetadataForSupport ($ providerId , $ modelRequirements );
142141 if (!empty ($ providerResults )) {
143- $ providerInstance = $ this ->getProviderInstance ($ providerId );
144-
145- // Validate that provider has metadata method
146- if (!method_exists ($ providerInstance , 'metadata ' )) {
147- continue ;
148- }
149-
150- $ providerMetadata = $ providerInstance ->metadata ();
151- if (!$ providerMetadata instanceof ProviderMetadata) {
152- continue ;
153- }
142+ // Use static method from ProviderInterface
143+ /** @var class-string<ProviderInterface> $className */
144+ $ providerMetadata = $ className ::metadata ();
154145
155146 $ results [] = new ProviderModelsMetadata (
156147 $ providerMetadata ,
@@ -175,11 +166,21 @@ public function findProviderModelsMetadataForSupport(
175166 string $ idOrClassName ,
176167 ModelRequirements $ modelRequirements
177168 ): array {
178- $ instance = $ this ->getProviderInstance ($ idOrClassName );
169+ $ className = $ this ->resolveProviderClassName ($ idOrClassName );
170+
171+ // Use static method from ProviderInterface
172+ /** @var class-string<ProviderInterface> $className */
173+ $ modelMetadataDirectory = $ className ::modelMetadataDirectory ();
179174
180- // TODO: Get model metadata directory when ProviderInterface is available
181- // For now, return empty array as placeholder
182- return [];
175+ // Filter models that meet requirements
176+ $ matchingModels = [];
177+ foreach ($ modelMetadataDirectory ->listModelMetadata () as $ modelMetadata ) {
178+ if ($ modelMetadata ->meetsRequirements ($ modelRequirements )) {
179+ $ matchingModels [] = $ modelMetadata ;
180+ }
181+ }
182+
183+ return $ matchingModels ;
183184 }
184185
185186 /**
@@ -189,26 +190,27 @@ public function findProviderModelsMetadataForSupport(
189190 *
190191 * @param string $idOrClassName The provider ID or class name.
191192 * @param string $modelId The model identifier.
192- * @param ModelConfig $modelConfig The model configuration.
193- * @return object The configured model instance.
193+ * @param ModelConfig|null $modelConfig The model configuration.
194+ * @return ModelInterface The configured model instance.
194195 * @throws InvalidArgumentException If provider or model is not found.
195196 */
196- public function getProviderModel (string $ idOrClassName , string $ modelId , ModelConfig $ modelConfig ): object
197+ public function getProviderModel (string $ idOrClassName , string $ modelId , ? ModelConfig $ modelConfig = null ): ModelInterface
197198 {
198- $ instance = $ this ->getProviderInstance ($ idOrClassName );
199+ $ className = $ this ->resolveProviderClassName ($ idOrClassName );
199200
200- // TODO: Call model() method when ProviderInterface is available
201- throw new InvalidArgumentException ('Model instantiation not yet implemented ' );
201+ // Use static method from ProviderInterface
202+ /** @var class-string<ProviderInterface> $className */
203+ return $ className ::model ($ modelId , $ modelConfig );
202204 }
203205
204206 /**
205- * Gets or creates a provider instance .
207+ * Gets the class name for a registered provider (handles both ID and class name input) .
206208 *
207209 * @param string $idOrClassName The provider ID or class name.
208- * @return object The provider instance .
210+ * @return string The provider class name .
209211 * @throws InvalidArgumentException If provider is not registered.
210212 */
211- private function getProviderInstance (string $ idOrClassName ): object
213+ private function resolveProviderClassName (string $ idOrClassName ): string
212214 {
213215 // Handle both ID and class name
214216 $ className = $ this ->providerClassNames [$ idOrClassName ] ?? $ idOrClassName ;
@@ -219,14 +221,6 @@ private function getProviderInstance(string $idOrClassName): object
219221 );
220222 }
221223
222- // Use cached instance if available
223- if (isset ($ this ->providerInstances [$ className ])) {
224- return $ this ->providerInstances [$ className ];
225- }
226-
227- // Create and cache new instance
228- $ this ->providerInstances [$ className ] = new $ className ();
229-
230- return $ this ->providerInstances [$ className ];
224+ return $ className ;
231225 }
232226}
0 commit comments