| @@ -8,8 +8,10 @@ | ||
| 8 | 8 | */ |
| 9 | 9 | |
| 10 | 10 | namespace IvyForms\Plugin; |
| 11 | 11 | |
| 12 | +use IvyForms\Infrastructure\WP\MCP\McpFeatureGate; | |
| 13 | +use IvyForms\Services\Ai\AiAvailability; | |
| 12 | 14 | use IvyForms\Services\Settings\SettingsService; |
| 13 | 15 | |
| 14 | 16 | /** |
| 15 | 17 | * AdminHooks |
| @@ -42,9 +44,8 @@ | ||
| 42 | 44 | { |
| 43 | 45 | add_action('admin_init', [$this, 'adminInit']); |
| 44 | 46 | add_filter('admin_body_class', [$this, 'addAdminBodyClass']); |
| 45 | 47 | add_action('admin_enqueue_scripts', [$this, 'adminScripts']); |
| 46 | - add_action('admin_enqueue_scripts', [$this, 'dequeueElementorScripts'], 999); | |
| 47 | 48 | } |
| 48 | 49 | |
| 49 | 50 | /** |
| 50 | 51 | * Handle admin initialization tasks |
| @@ -54,11 +55,25 @@ | ||
| 54 | 55 | public function adminInit(): void |
| 55 | 56 | { |
| 56 | 57 | $this->checkVersionAndHandleActivation(); |
| 57 | 58 | $this->removeAdminNotices(); |
| 59 | + $this->maybeWarmAiAvailabilityCache(); | |
| 58 | 60 | } |
| 59 | 61 | |
| 60 | 62 | /** |
| 63 | + * Warm AI capability cache outside MenuService::render() so admin UI never | |
| 64 | + * triggers provider probes while localizing scripts. | |
| 65 | + */ | |
| 66 | + private function maybeWarmAiAvailabilityCache(): void | |
| 67 | + { | |
| 68 | + if (!$this->isIvyFormsAdminPage()) { | |
| 69 | + return; | |
| 70 | + } | |
| 71 | + | |
| 72 | + AiAvailability::maybeRefreshTextGenerationSupport(); | |
| 73 | + } | |
| 74 | + | |
| 75 | + /** | |
| 61 | 76 | * Enqueue admin scripts (deactivation modal and Angie MCP server for Elementor AI integration) |
| 62 | 77 | * |
| 63 | 78 | * @param string $hook Current admin page hook |
| 64 | 79 | * @return void |
| @@ -73,10 +88,8 @@ | ||
| 73 | 88 | [], |
| 74 | 89 | IVYFORMS_VERSION, |
| 75 | 90 | true |
| 76 | 91 | ); |
| 77 | - $settingsService = new SettingsService(); | |
| 78 | - $deleteOnUninstall = $settingsService->getSetting('general', 'delete_on_uninstall'); | |
| 79 | 92 | wp_localize_script( |
| 80 | 93 | 'ivyforms-deactivation-modal', |
| 81 | 94 | 'ivyformsData', |
| 82 | 95 | [ |
| @@ -83,24 +96,19 @@ | ||
| 83 | 96 | 'version' => IVYFORMS_VERSION, |
| 84 | 97 | 'pluginUrl' => IVYFORMS_URL, |
| 85 | 98 | 'restApiUrl' => rest_url('ivyforms/v1/deactivation-feedback'), |
| 86 | 99 | 'restNonce' => wp_create_nonce('wp_rest'), |
| 87 | - 'deleteOnUninstall' => $deleteOnUninstall, | |
| 88 | - 'i18n' => [ | |
| 89 | - 'warningTitle' => __('Warning', 'ivyforms'), | |
| 90 | - 'warningMessage' => __( | |
| 91 | - 'All IvyForms database tables and settings will be deleted when ' | |
| 92 | - . 'this plugin is deactivated. To prevent this,', | |
| 93 | - 'ivyforms' | |
| 94 | - ), | |
| 95 | - 'warningLinkText' => __('disable this option in settings', 'ivyforms'), | |
| 96 | - ] | |
| 97 | 100 | ] |
| 98 | 101 | ); |
| 99 | 102 | } |
| 100 | 103 | |
| 101 | - // Angie MCP server for Elementor AI integration | |
| 102 | - if (function_exists('is_plugin_active') && is_plugin_active('angie/angie.php')) { | |
| 104 | + // Angie MCP client — proxy JS talks to the PHP MCP REST route. | |
| 105 | + // Only load when Angie is active and IvyForms MCP itself is enabled. | |
| 106 | + if ( | |
| 107 | + function_exists('is_plugin_active') | |
| 108 | + && is_plugin_active('angie/angie.php') | |
| 109 | + && McpFeatureGate::isEnabled() | |
| 110 | + ) { | |
| 103 | 111 | $wpVersion = get_bloginfo('version'); |
| 104 | 112 | if (version_compare($wpVersion, '6.5', '<')) { |
| 105 | 113 | return; |
| 106 | 114 | } |
| @@ -107,8 +115,13 @@ | ||
| 107 | 115 | $mcpServerPath = IVYFORMS_PATH . '/frontend/dist/ivyforms-angie.js'; |
| 108 | 116 | if (!file_exists($mcpServerPath)) { |
| 109 | 117 | return; |
| 110 | 118 | } |
| 119 | + | |
| 120 | + // Script modules cannot use wp_localize_script(); ensure core wpApiSettings | |
| 121 | + // (root + nonce) exists on every admin page where Angie loads this module. | |
| 122 | + wp_enqueue_script('wp-api-request'); | |
| 123 | + | |
| 111 | 124 | // @phpstan-ignore-next-line |
| 112 | 125 | wp_enqueue_script_module( |
| 113 | 126 | 'ivyforms-angie-mcp', |
| 114 | 127 | IVYFORMS_URL . 'frontend/dist/ivyforms-angie.js', |
| @@ -199,35 +212,6 @@ | ||
| 199 | 212 | $classes .= ' ivyforms-fullscreen-mode '; |
| 200 | 213 | } |
| 201 | 214 | |
| 202 | 215 | return $classes; |
| 203 | - } | |
| 204 | - | |
| 205 | - /** | |
| 206 | - * Dequeue Elementor admin scripts on IvyForms pages | |
| 207 | - * Prevents Elementor keyboard shortcuts (Ctrl+E for Finder) from conflicting with IvyForms | |
| 208 | - * | |
| 209 | - * @return void | |
| 210 | - */ | |
| 211 | - public function dequeueElementorScripts(): void | |
| 212 | - { | |
| 213 | - // Only dequeue on IvyForms admin pages | |
| 214 | - if (!$this->isIvyFormsAdminPage()) { | |
| 215 | - return; | |
| 216 | - } | |
| 217 | - | |
| 218 | - // Check if Elementor is active | |
| 219 | - if (!defined('ELEMENTOR_VERSION')) { | |
| 220 | - return; | |
| 221 | - } | |
| 222 | - | |
| 223 | - // Dequeue Elementor's common admin scripts that include keyboard shortcuts | |
| 224 | - wp_dequeue_script('elementor-common'); | |
| 225 | - wp_dequeue_script('elementor-admin-app'); | |
| 226 | - wp_dequeue_script('elementor-admin'); | |
| 227 | - | |
| 228 | - // Also deregister to prevent other plugins from loading them | |
| 229 | - wp_deregister_script('elementor-common'); | |
| 230 | - wp_deregister_script('elementor-admin-app'); | |
| 231 | - wp_deregister_script('elementor-admin'); | |
| 232 | 216 | } |
| 233 | 217 | } |