PluginProbe
phpinfo() WP – Site Health, PHP Compatibility & Server Audit / 7.2.5
phpinfo() WP – Site Health, PHP Compatibility & Server Audit v7.2.5
7.2.7 7.2.6 7.2.5 7.2.4 7.2.3 7.2.0 7.2.1 7.2.2 7.1.0 7.0.3 7.0.4 7.0.5 trunk 6.0 7.0.0 7.0.1 7.0.2
phpinfo-wp / includes / class-ai-explain.php

class-ai-explain.php in phpinfo() WP – Site Health, PHP Compatibility & Server Audit 7.2.5, at includes/class-ai-explain.php

103 lines 5.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 defined('ABSPATH') or die('Unauthorized Access');
3
4 // WP 7.0 AI Client integration. Adds an "Explain with AI" capability that
5 // turns a php.ini directive name, a failing config check, or a security
6 // header into a short plain-English explanation. Credentials are managed
7 // entirely by the core Connectors API — we never touch API keys.
8 //
9 // Falls back silently on cores without wp_ai_client_prompt() so the rest
10 // of the plugin keeps working on WP < 7.0.
11
12 class Phpinfo_WP_AI_Explain {
13
14 const NONCE = 'phpinfowp_ai_explain';
15 const ACTION = 'phpinfowp_ai_explain';
16
17 public static function register(): void {
18 if (!self::available()) return;
19 add_action('wp_ajax_' . self::ACTION, [self::class, 'ajax_explain']);
20 }
21
22 public static function available(): bool {
23 return function_exists('wp_ai_client_prompt');
24 }
25
26 // Localized data for the JS handler. Returns an empty array when the
27 // AI Client isn't available so the JS can hide the button.
28 public static function js_config(): array {
29 return [
30 'available' => self::available(),
31 'action' => self::ACTION,
32 'nonce' => wp_create_nonce(self::NONCE),
33 'ajax_url' => admin_url('admin-ajax.php'),
34 'i18n' => [
35 'explain' => __('Explain with AI', 'phpinfo-wp'),
36 'thinking' => __('Asking AI…', 'phpinfo-wp'),
37 'error' => __('AI request failed.', 'phpinfo-wp'),
38 ],
39 ];
40 }
41
42 public static function ajax_explain(): void {
43 check_ajax_referer(self::NONCE, 'nonce');
44 if (!current_user_can('manage_options')) {
45 wp_send_json_error(['message' => __('Forbidden.', 'phpinfo-wp')], 403);
46 }
47 if (!self::available()) {
48 wp_send_json_error(['message' => __('AI Client is not available. Requires WordPress 7.0+ with a configured AI connector.', 'phpinfo-wp')], 501);
49 }
50
51 $topic = sanitize_key($_POST['topic'] ?? '');
52 $context = sanitize_text_field(wp_unslash($_POST['context'] ?? ''));
53 $value = sanitize_text_field(wp_unslash($_POST['value'] ?? ''));
54
55 $prompt = self::build_prompt($topic, $context, $value);
56 if ($prompt === '') {
57 wp_send_json_error(['message' => __('Unknown topic.', 'phpinfo-wp')], 400);
58 }
59
60 $result = wp_ai_client_prompt($prompt)->generate_text();
61 if (is_wp_error($result)) {
62 wp_send_json_error(['message' => $result->get_error_message()], 502);
63 }
64 wp_send_json_success(['text' => (string) $result]);
65 }
66
67 // Prompts are intentionally short, factual, and bounded — long answers
68 // waste the user's connector budget and clutter the inline UI.
69 private static function build_prompt(string $topic, string $context, string $value): string {
70 switch ($topic) {
71 case 'directive':
72 return sprintf(
73 'Explain the PHP directive `%s` in the context of a WordPress site. Cover: what it does, recommended value, and the typical symptom when it is misconfigured. Use 3–4 short sentences. Plain text, no markdown.',
74 $context
75 );
76 case 'config_issue':
77 return sprintf(
78 'A WordPress site has the PHP directive `%s` currently set to `%s`. Explain in 3–4 short sentences why this value is below the recommended setting, the user-visible symptom (e.g. uploads failing, builder breaking), and the safest way to fix it on a shared host. Plain text, no markdown.',
79 $context, $value !== '' ? $value : '(not set)'
80 );
81 case 'header':
82 return sprintf(
83 'Explain the HTTP security header `%s` for a WordPress site. Cover: what it protects against, a sensible recommended value, and the realistic risk of leaving it off. Use 3–4 short sentences. Plain text, no markdown.',
84 $context
85 );
86 case 'extension':
87 return sprintf(
88 'Explain the PHP extension `%s` in the context of a WordPress site. Cover: what it provides, common plugins that need it, and the symptom when it is missing. Use 3–4 short sentences. Plain text, no markdown.',
89 $context
90 );
91 case 'update_break':
92 // $context = API name (e.g. ".live()" or "get_currentuserinfo()"),
93 // $value = target WordPress version being audited.
94 return sprintf(
95 'A WordPress plugin or theme calls `%s`, which is flagged when updating to WordPress %s. Explain in 3–4 short sentences: what this API was, why it is deprecated or removed in modern WordPress, the realistic symptom on the site after the update (e.g. JavaScript stops working, PHP notice in the log), and the modern replacement. Plain text, no markdown.',
96 $context, $value !== '' ? $value : 'a newer version'
97 );
98 default:
99 return '';
100 }
101 }
102 }
103