PluginProbe
AI / 0.2.0
AI v0.2.0
1.3.0 1.2.0 1.1.0 1.0.2 1.0.1 1.0.0 0.9.0 trunk 0.1.1 0.2.0 0.2.1 0.3.0 0.3.1 0.4.0 0.4.1 0.5.0 0.6.0 0.7.0 0.8.0
ai / includes / Experiment_Loader.php

Experiment_Loader.php in AI 0.2.0, at includes/Experiment_Loader.php

233 lines 6.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Experiment Loader class.
4 *
5 * @package WordPress\AI
6 */
7
8 declare( strict_types=1 );
9
10 namespace WordPress\AI;
11
12 use Throwable;
13 use WordPress\AI\Contracts\Experiment;
14 use WordPress\AI\Exception\Invalid_Experiment_Exception;
15 use WordPress\AI\Exception\Invalid_Experiment_Metadata_Exception;
16
17 /**
18 * Orchestrates experiment initialization and registration.
19 *
20 * This class is responsible for loading and initializing experiments from the registry.
21 * It decouples the initialization logic from the registry itself.
22 *
23 * @since 0.1.0
24 */
25 final class Experiment_Loader {
26 /**
27 * Experiment registry instance.
28 *
29 * @since 0.1.0
30 * @var \WordPress\AI\Experiment_Registry
31 */
32 private \WordPress\AI\Experiment_Registry $registry;
33
34 /**
35 * Whether experiments have been initialized.
36 *
37 * @since 0.1.0
38 * @var bool
39 */
40 private bool $initialized = false;
41
42 /**
43 * Constructor.
44 *
45 * @since 0.1.0
46 *
47 * @param \WordPress\AI\Experiment_Registry $registry The experiment registry instance.
48 */
49 public function __construct( Experiment_Registry $registry ) {
50 $this->registry = $registry;
51 }
52
53 /**
54 * Registers default experiments.
55 *
56 * This is where built-in experiments are registered. Third-party experiments
57 * should use the 'ai_experiments_register_experiments' action hook.
58 *
59 * @since 0.1.0
60 *
61 * @throws \WordPress\AI\Exception\Invalid_Experiment_Exception If an experiment does not implement the Experiment interface.
62 */
63 public function register_default_experiments(): void {
64 $experiments = $this->get_default_experiments();
65
66 // Register all experiments with type validation.
67 foreach ( $experiments as $experiment ) {
68 // Skip invalid experiment instances.
69 if ( ! $experiment instanceof Experiment ) {
70 throw new Invalid_Experiment_Exception(
71 esc_html__( 'Attempted to register invalid experiment. Must implement Experiment interface.', 'ai' )
72 );
73 }
74
75 $this->registry->register_experiment( $experiment );
76 }
77
78 /**
79 * Allows registration of custom experiments.
80 *
81 * Third-party developers can use this action to register their own experiments.
82 *
83 * Example:
84 * ```php
85 * add_action( 'ai_experiments_register_experiments', function( $registry ) {
86 * $registry->register_experiment( new My_Custom_Experiment() );
87 * } );
88 * ```
89 *
90 * @since 0.1.0
91 *
92 * @param \WordPress\AI\Experiment_Registry $registry The experiment registry instance.
93 */
94 do_action( 'ai_experiments_register_experiments', $this->registry );
95 }
96
97 /**
98 * Gets default built-in experiments.
99 *
100 * @since 0.1.0
101 *
102 * @return array<\WordPress\AI\Contracts\Experiment> Array of default experiment instances.
103 * @throws \WordPress\AI\Exception\Invalid_Experiment_Exception If an experiment class does not exist (caught internally).
104 */
105 private function get_default_experiments(): array {
106 $experiment_classes = array(
107 \WordPress\AI\Experiments\Abilities_Explorer\Abilities_Explorer::class,
108 \WordPress\AI\Experiments\Excerpt_Generation\Excerpt_Generation::class,
109 \WordPress\AI\Experiments\Image_Generation\Image_Generation::class,
110 \WordPress\AI\Experiments\Summarization\Summarization::class,
111 \WordPress\AI\Experiments\Title_Generation\Title_Generation::class,
112 );
113
114 /**
115 * Filters the list of default experiment classes or instances.
116 *
117 * Allows developers to add, remove, or replace default experiments.
118 * Can accept both class names (strings) and experiment instances.
119 *
120 * @since 0.1.0
121 *
122 * @param array $experiment_classes Array of experiment class names or instances.
123 */
124 $items = apply_filters( 'ai_experiments_default_experiment_classes', $experiment_classes );
125
126 $experiments = array();
127 foreach ( $items as $item ) {
128 try {
129 // Support both class names and pre-instantiated instances.
130 if ( is_string( $item ) && class_exists( $item ) ) {
131 /** @var class-string<\WordPress\AI\Contracts\Experiment> $item */
132 $experiments[] = new $item();
133 } elseif ( $item instanceof Experiment ) {
134 $experiments[] = $item;
135 } elseif ( is_string( $item ) ) {
136 // Class doesn't exist - throw exception.
137 throw new Invalid_Experiment_Exception(
138 sprintf(
139 /* translators: %s: Experiment class name. */
140 esc_html__( 'Experiment class "%s" does not exist.', 'ai' ),
141 esc_html( $item )
142 )
143 );
144 }
145 } catch ( Invalid_Experiment_Metadata_Exception $e ) {
146 // Skip experiments with invalid metadata.
147 _doing_it_wrong(
148 __METHOD__,
149 sprintf(
150 /* translators: 1: Experiment class name, 2: Error message. */
151 esc_html__( 'Failed to instantiate experiment "%1$s": %2$s', 'ai' ),
152 is_string( $item ) ? esc_html( $item ) : esc_html( (string) get_class( $item ) ),
153 esc_html( $e->getMessage() )
154 ),
155 '0.1.0'
156 );
157 } catch ( Throwable $t ) {
158 // Skip experiments that fail to instantiate.
159 _doing_it_wrong(
160 __METHOD__,
161 sprintf(
162 /* translators: 1: Experiment class name, 2: Error message. */
163 esc_html__( 'Experiment instantiation error for "%1$s": %2$s', 'ai' ),
164 is_string( $item ) ? esc_html( $item ) : esc_html( (string) get_class( $item ) ),
165 esc_html( $t->getMessage() )
166 ),
167 '0.1.0'
168 );
169 }
170 }
171
172 return $experiments;
173 }
174
175 /**
176 * Initializes all enabled experiments.
177 *
178 * Loops through all registered experiments and calls their register() method
179 * if they are enabled.
180 *
181 * @since 0.1.0
182 */
183 public function initialize_experiments(): void {
184 if ( $this->initialized ) {
185 return;
186 }
187
188 /**
189 * Filters whether to enable AI experiments.
190 *
191 * @since 0.1.0
192 *
193 * @param bool $enabled Whether to enable AI experiments.
194 */
195 $experiments_enabled = apply_filters( 'ai_experiments_enabled', true );
196
197 if ( ! $experiments_enabled ) {
198 $this->initialized = true;
199 return;
200 }
201
202 foreach ( $this->registry->get_all_experiments() as $experiment ) {
203 // Skip if experiment is disabled.
204 if ( ! $experiment->is_enabled() ) {
205 continue;
206 }
207
208 // Register the experiment.
209 $experiment->register();
210 }
211
212 /**
213 * Fires after all experiments have been initialized.
214 *
215 * @since 0.1.0
216 */
217 do_action( 'ai_experiments_initialized' );
218
219 $this->initialized = true;
220 }
221
222 /**
223 * Checks if experiments have been initialized.
224 *
225 * @since 0.1.0
226 *
227 * @return bool True if initialized, false otherwise.
228 */
229 public function is_initialized(): bool {
230 return $this->initialized;
231 }
232 }
233