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 / Abstracts / Abstract_Ability.php

Abstract_Ability.php in AI 0.2.0, at includes/Abstracts/Abstract_Ability.php

195 lines 5.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Abstract Ability base class.
4 *
5 * @package WordPress\AI\Abstracts
6 */
7
8 declare( strict_types=1 );
9
10 namespace WordPress\AI\Abstracts;
11
12 use ReflectionClass;
13 use WP_Ability;
14
15 /**
16 * Base implementation for a WordPress Ability.
17 *
18 * @since 0.1.0
19 */
20 abstract class Abstract_Ability extends WP_Ability {
21
22 /**
23 * Constructor.
24 *
25 * @since 0.1.0
26 *
27 * @param string $name The name of the ability.
28 * @param array<string,mixed> $properties The properties of the ability. Must include `label`.
29 */
30 public function __construct( string $name, array $properties = array() ) {
31 parent::__construct(
32 $name,
33 array(
34 'label' => $properties['label'] ?? '',
35 'description' => $properties['description'] ?? '',
36 'category' => $this->category(),
37 'input_schema' => $this->input_schema(),
38 'output_schema' => $this->output_schema(),
39 'execute_callback' => array( $this, 'execute_callback' ),
40 'permission_callback' => array( $this, 'permission_callback' ),
41 'meta' => $this->meta(),
42 )
43 );
44 }
45
46 /**
47 * Returns the category of the ability.
48 *
49 * @since 0.1.0
50 *
51 * @return string The category of the ability.
52 */
53 protected function category(): string {
54 return AI_EXPERIMENTS_DEFAULT_ABILITY_CATEGORY;
55 }
56
57 /**
58 * Returns the REST API path of the ability.
59 *
60 * @since 0.2.0
61 *
62 * @param string $experiment_id The ID of the experiment.
63 * @return string The REST API path of the ability.
64 */
65 public static function path( string $experiment_id = '' ): string {
66 return 'wp-abilities/v1/abilities/ai/' . $experiment_id . '/run';
67 }
68
69 /**
70 * Returns the input schema of the ability.
71 *
72 * @since 0.1.0
73 *
74 * @return array<string, mixed> The input schema of the ability.
75 */
76 abstract protected function input_schema(): array;
77
78 /**
79 * Returns the output schema of the ability.
80 *
81 * @since 0.1.0
82 *
83 * @return array<string, mixed> The output schema of the ability.
84 */
85 abstract protected function output_schema(): array;
86
87 /**
88 * Executes the ability with the given input arguments.
89 *
90 * @since 0.1.0
91 *
92 * @param mixed $input The input arguments to the ability.
93 * @return mixed|\WP_Error The result of the ability execution, or a WP_Error on failure.
94 */
95 abstract protected function execute_callback( $input );
96
97 /**
98 * Checks whether the current user has permission to execute the ability with the given input arguments.
99 *
100 * @since 0.1.0
101 *
102 * @param mixed $input The input arguments to the ability.
103 * @return bool|\WP_Error True if the user has permission, WP_Error otherwise.
104 */
105 abstract protected function permission_callback( $input );
106
107 /**
108 * Returns the meta of the ability.
109 *
110 * @since 0.1.0
111 *
112 * @return array<string, mixed> The meta of the ability.
113 */
114 abstract protected function meta(): array;
115
116 /**
117 * Gets the system instruction for the feature.
118 *
119 * @since 0.1.0
120 *
121 * @param string|null $filename Optional. Explicit filename to load. If not provided,
122 * attempts to load `system-instruction.php` or `prompt.php`.
123 * @param array<string, mixed> $data Optional. Data to expose to the system instruction file.
124 * This data will be extracted as variables available in the file scope.
125 * @return string The system instruction for the feature.
126 */
127 public function get_system_instruction( ?string $filename = null, array $data = array() ): string {
128 return $this->load_system_instruction_from_file( $filename, $data );
129 }
130
131 /**
132 * Loads system instruction from a PHP file in the feature's directory.
133 *
134 * PHP files should return a string directly, e.g.:
135 * ```php
136 * <?php
137 * return 'Your system instruction text here...';
138 * ```
139 *
140 * If data is provided, it will be extracted as variables available in the file scope.
141 * For example, if you pass `array( 'length' => 'short' )`, the variable `$length`
142 * will be available in the system instruction file.
143 *
144 * @since 0.1.0
145 *
146 * @param string|null $filename Optional. Explicit filename to load. If not provided,
147 * attempts to load `system-instruction.php`.
148 * @param array<string, mixed> $data Optional. Data to expose to the system instruction file.
149 * This data will be extracted as variables available in the file scope.
150 * @return string The contents of the file, or empty string if file not found.
151 */
152 protected function load_system_instruction_from_file( ?string $filename = null, array $data = array() ): string {
153 // Get the feature's directory using reflection.
154 $reflection = new ReflectionClass( $this );
155 $file_name = $reflection->getFileName();
156
157 if ( ! $file_name ) {
158 return '';
159 }
160
161 $feature_dir = dirname( $file_name );
162
163 // Extract data into variables for use in the included file.
164 if ( ! empty( $data ) ) {
165 extract( $data, EXTR_SKIP ); // phpcs:ignore WordPress.PHP.DontExtract.extract_extract
166 }
167
168 // If explicit filename provided, use it.
169 if ( null !== $filename ) {
170 $file_path = trailingslashit( $feature_dir ) . $filename;
171
172 if ( file_exists( $file_path ) && is_readable( $file_path ) ) {
173 // PHP files should return a string directly.
174 $content = require_once $file_path; // phpcs:ignore WordPressVIPMinimum.Files.IncludingFile.UsingVariable
175
176 return is_string( $content ) ? wp_strip_all_tags( $content ) : '';
177 }
178
179 return '';
180 }
181
182 // Automatic detection if no filename provided.
183 $file_path = trailingslashit( $feature_dir ) . 'system-instruction.php';
184
185 if ( file_exists( $file_path ) && is_readable( $file_path ) ) {
186 // PHP files should return a string directly.
187 $content = require $file_path; // phpcs:ignore WordPressVIPMinimum.Files.IncludingFile.UsingVariable
188
189 return is_string( $content ) ? wp_strip_all_tags( $content ) : '';
190 }
191
192 return '';
193 }
194 }
195