PluginProbe
AI / trunk
AI vtrunk
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 / Experiments / Content_Classification / Content_Classification.php

Content_Classification.php in AI trunk, at includes/Experiments/Content_Classification/Content_Classification.php

313 lines 7.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Content classification experiment implementation.
4 *
5 * @package WordPress\AI
6 */
7
8 declare( strict_types=1 );
9
10 namespace WordPress\AI\Experiments\Content_Classification;
11
12 use WordPress\AI\Abilities\Content_Classification\Content_Classification as Content_Classification_Ability;
13 use WordPress\AI\Abstracts\Abstract_Feature;
14 use WordPress\AI\Asset_Loader;
15 use WordPress\AI\Experiments\Experiment_Category;
16 use WordPress\AI\Settings\Settings_Registration;
17
18 use function WordPress\AI\get_min_content_length;
19
20 if ( ! defined( 'ABSPATH' ) ) {
21 exit;
22 }
23
24 /**
25 * Content classification experiment.
26 *
27 * Provides AI-powered suggestions for post taxonomies
28 * based on a comprehensive analysis of the post content.
29 *
30 * @since 0.7.0
31 */
32 class Content_Classification extends Abstract_Feature {
33
34 /**
35 * The default taxonomy strategy.
36 *
37 * @since 0.7.0
38 *
39 * @var string
40 */
41 public const STRATEGY_EXISTING_ONLY = 'existing_only';
42
43 /**
44 * The strategy that allows new term suggestions.
45 *
46 * @since 0.7.0
47 *
48 * @var string
49 */
50 public const STRATEGY_ALLOW_NEW = 'allow_new';
51
52 /**
53 * The default maximum number of suggestions.
54 *
55 * @since 0.7.0
56 *
57 * @var int
58 */
59 public const DEFAULT_MAX_SUGGESTIONS = 5;
60
61 /**
62 * The minimum allowed number of suggestions.
63 *
64 * @since 0.7.0
65 *
66 * @var int
67 */
68 public const MIN_SUGGESTIONS = 1;
69
70 /**
71 * The maximum allowed number of suggestions.
72 *
73 * @since 0.7.0
74 *
75 * @var int
76 */
77 public const MAX_SUGGESTIONS = 10;
78
79 /**
80 * {@inheritDoc}
81 */
82 public static function get_id(): string {
83 return 'content-classification';
84 }
85
86 /**
87 * {@inheritDoc}
88 */
89 protected function load_metadata(): array {
90 return array(
91 'label' => __( 'Content Classification', 'ai' ),
92 'description' => __( 'AI-powered suggestions for post tags and categories based on content analysis. Requires an AI connector that includes support for text generation models.', 'ai' ),
93 'category' => Experiment_Category::EDITOR,
94 );
95 }
96
97 /**
98 * {@inheritDoc}
99 */
100 public function register(): void {
101 add_action( 'wp_abilities_api_init', array( $this, 'register_abilities' ) );
102 add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) );
103 }
104
105 /**
106 * Registers any needed abilities.
107 *
108 * @since 0.7.0
109 */
110 public function register_abilities(): void {
111 wp_register_ability(
112 'ai/' . $this->get_id(),
113 array(
114 'label' => $this->get_label(),
115 'description' => $this->get_description(),
116 'ability_class' => Content_Classification_Ability::class,
117 ),
118 );
119 }
120
121 /**
122 * Enqueues and localizes the admin script.
123 *
124 * @since 0.7.0
125 *
126 * @param string $hook_suffix The current admin page hook suffix.
127 */
128 public function enqueue_assets( string $hook_suffix ): void {
129 // Load asset in new post and edit post screens only.
130 if ( 'post.php' !== $hook_suffix && 'post-new.php' !== $hook_suffix ) {
131 return;
132 }
133
134 $screen = get_current_screen();
135
136 // Load the assets only if the post type supports categories or tags and is not an attachment.
137 // Also check if the user can manage categories.
138 if (
139 ! $screen ||
140 ! current_user_can( 'manage_categories' ) ||
141 in_array( $screen->post_type, array( 'attachment' ), true ) ||
142 (
143 ! is_object_in_taxonomy( $screen->post_type, 'category' ) &&
144 ! is_object_in_taxonomy( $screen->post_type, 'post_tag' )
145 )
146 ) {
147 return;
148 }
149
150 Asset_Loader::enqueue_script( 'content_classification', 'experiments/content-classification', array( 'include_core_abilities' => true ) );
151 Asset_Loader::enqueue_style( 'content_classification', 'experiments/content-classification' );
152 Asset_Loader::localize_script(
153 'content_classification',
154 'ContentClassificationData',
155 array(
156 'enabled' => $this->is_enabled(),
157 'strategy' => $this->get_strategy(),
158 'maxSuggestions' => $this->get_max_suggestions(),
159 'minContentLength' => get_min_content_length( 'content-classification', 250 ),
160 )
161 );
162 }
163
164 /**
165 * Registers experiment-specific settings.
166 *
167 * @since 0.7.0
168 */
169 public function register_settings(): void {
170 register_setting(
171 Settings_Registration::OPTION_GROUP,
172 static::get_field_option_name( 'strategy' ),
173 array(
174 'type' => 'string',
175 'default' => self::STRATEGY_EXISTING_ONLY,
176 'sanitize_callback' => array( $this, 'sanitize_strategy' ),
177 'show_in_rest' => array(
178 'schema' => array(
179 'type' => 'string',
180 'enum' => array( self::STRATEGY_EXISTING_ONLY, self::STRATEGY_ALLOW_NEW ),
181 ),
182 ),
183 )
184 );
185
186 register_setting(
187 Settings_Registration::OPTION_GROUP,
188 static::get_field_option_name( 'max_suggestions' ),
189 array(
190 'type' => 'integer',
191 'default' => self::DEFAULT_MAX_SUGGESTIONS,
192 'sanitize_callback' => array( $this, 'sanitize_max_suggestions' ),
193 'show_in_rest' => array(
194 'schema' => array(
195 'type' => 'integer',
196 'minimum' => self::MIN_SUGGESTIONS,
197 'maximum' => self::MAX_SUGGESTIONS,
198 ),
199 ),
200 )
201 );
202 }
203
204 /**
205 * {@inheritDoc}
206 */
207 public function get_settings_fields(): array {
208 return array(
209 array(
210 'id' => 'strategy',
211 'label' => __( 'Taxonomy strategy', 'ai' ),
212 'type' => 'text',
213 'default' => self::STRATEGY_EXISTING_ONLY,
214 'elements' => array(
215 array(
216 'value' => self::STRATEGY_EXISTING_ONLY,
217 'label' => __( 'Only suggest existing terms', 'ai' ),
218 ),
219 array(
220 'value' => self::STRATEGY_ALLOW_NEW,
221 'label' => __( 'Suggest new terms based on context', 'ai' ),
222 ),
223 ),
224 ),
225 array(
226 'id' => 'max_suggestions',
227 'label' => __( 'Maximum suggestions', 'ai' ),
228 'type' => 'integer',
229 'default' => self::DEFAULT_MAX_SUGGESTIONS,
230 'isValid' => array(
231 'min' => self::MIN_SUGGESTIONS,
232 'max' => self::MAX_SUGGESTIONS,
233 ),
234 ),
235 );
236 }
237
238 /**
239 * Sanitizes the strategy setting.
240 *
241 * @since 0.7.0
242 *
243 * @param mixed $value The value to sanitize.
244 * @return string The sanitized strategy value.
245 */
246 public function sanitize_strategy( $value ): string {
247 $valid = array( self::STRATEGY_EXISTING_ONLY, self::STRATEGY_ALLOW_NEW );
248
249 return in_array( $value, $valid, true ) ? $value : self::STRATEGY_EXISTING_ONLY;
250 }
251
252 /**
253 * Sanitizes the max suggestions setting.
254 *
255 * @since 0.7.0
256 *
257 * @param mixed $value The value to sanitize.
258 * @return int The sanitized max suggestions value.
259 */
260 public function sanitize_max_suggestions( $value ): int {
261 $value = absint( $value );
262
263 return max( self::MIN_SUGGESTIONS, min( self::MAX_SUGGESTIONS, $value ) );
264 }
265
266 /**
267 * Gets the strategy to use for content classification.
268 *
269 * @since 0.7.0
270 *
271 * @return string The strategy to use.
272 */
273 public function get_strategy(): string {
274 $strategy = get_option( static::get_field_option_name( 'strategy' ), self::STRATEGY_EXISTING_ONLY );
275
276 /**
277 * Filters the strategy to use for content classification.
278 *
279 * @since 0.7.0
280 *
281 * @param string $strategy The strategy to use.
282 * @return string The filtered strategy.
283 */
284 $strategy = apply_filters( 'wpai_content_classification_strategy', $strategy );
285
286 // Return the sanitized strategy value.
287 return $this->sanitize_strategy( $strategy );
288 }
289
290 /**
291 * Gets the maximum number of suggestions to generate for content classification.
292 *
293 * @since 0.7.0
294 *
295 * @return int The maximum number of suggestions to generate.
296 */
297 public function get_max_suggestions(): int {
298 $max_suggestions = (int) get_option( static::get_field_option_name( 'max_suggestions' ), self::DEFAULT_MAX_SUGGESTIONS );
299
300 /**
301 * Filters the maximum number of suggestions to generate for content classification.
302 *
303 * @since 0.7.0
304 *
305 * @param int $max_suggestions The maximum number of suggestions to generate.
306 * @return int The filtered max suggestions.
307 */
308 return $this->sanitize_max_suggestions(
309 apply_filters( 'wpai_content_classification_max_suggestions', $max_suggestions )
310 );
311 }
312 }
313