PluginProbe
The Innovative Form Builder – IvyForms / 1.4.1
The Innovative Form Builder – IvyForms v1.4.1
1.5.1 1.5 1.4.1 1.4 trunk 0.1.2 0.2 0.2.1 0.3 0.3.1 0.4 0.5 0.6 0.6.1 0.6.1-backup 0.6.1.1 0.7 0.8 0.8.1 0.8.2 0.9 0.9.1 1.0 1.1 1.1.1 All 27 releases
ivyforms / backend / src / Plugin / AdminHooks.php

AdminHooks.php in The Innovative Form Builder – IvyForms 1.4.1, at backend/src/Plugin/AdminHooks.php

218 lines 6.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Admin Hooks Handler
5 *
6 * @package IvyForms
7 * @since 0.5.0
8 */
9
10 namespace IvyForms\Plugin;
11
12 use IvyForms\Infrastructure\WP\MCP\McpFeatureGate;
13 use IvyForms\Services\Ai\AiAvailability;
14 use IvyForms\Services\Settings\SettingsService;
15
16 /**
17 * AdminHooks
18 *
19 * Handles all admin-related hooks and functionality
20 */
21 class AdminHooks
22 {
23 /**
24 * Settings Service
25 */
26 private ?SettingsService $settingsService = null;
27
28 /**
29 * Constructor
30 *
31 * @param SettingsService|null $settingsService
32 */
33 public function __construct(?SettingsService $settingsService = null)
34 {
35 $this->settingsService = $settingsService;
36 }
37
38 /**
39 * Register admin hooks
40 *
41 * @return void
42 */
43 public function register(): void
44 {
45 add_action('admin_init', [$this, 'adminInit']);
46 add_filter('admin_body_class', [$this, 'addAdminBodyClass']);
47 add_action('admin_enqueue_scripts', [$this, 'adminScripts']);
48 }
49
50 /**
51 * Handle admin initialization tasks
52 *
53 * @return void
54 */
55 public function adminInit(): void
56 {
57 $this->checkVersionAndHandleActivation();
58 $this->removeAdminNotices();
59 $this->maybeWarmAiAvailabilityCache();
60 }
61
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 /**
76 * Enqueue admin scripts (deactivation modal and Angie MCP server for Elementor AI integration)
77 *
78 * @param string $hook Current admin page hook
79 * @return void
80 */
81 public function adminScripts(string $hook): void
82 {
83 // Deactivation modal on plugins page
84 if ($hook === 'plugins.php') {
85 wp_enqueue_script(
86 'ivyforms-deactivation-modal',
87 IVYFORMS_URL . 'frontend/assets/js/admin-deactivation-modal.js',
88 [],
89 IVYFORMS_VERSION,
90 true
91 );
92 wp_localize_script(
93 'ivyforms-deactivation-modal',
94 'ivyformsData',
95 [
96 'version' => IVYFORMS_VERSION,
97 'pluginUrl' => IVYFORMS_URL,
98 'restApiUrl' => rest_url('ivyforms/v1/deactivation-feedback'),
99 'restNonce' => wp_create_nonce('wp_rest'),
100 ]
101 );
102 }
103
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 ) {
111 $wpVersion = get_bloginfo('version');
112 if (version_compare($wpVersion, '6.5', '<')) {
113 return;
114 }
115 $mcpServerPath = IVYFORMS_PATH . '/frontend/dist/ivyforms-angie.js';
116 if (!file_exists($mcpServerPath)) {
117 return;
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
124 // @phpstan-ignore-next-line
125 wp_enqueue_script_module(
126 'ivyforms-angie-mcp',
127 IVYFORMS_URL . 'frontend/dist/ivyforms-angie.js',
128 array(),
129 IVYFORMS_VERSION
130 );
131 }
132 }
133
134 /**
135 * Check a plugin version and handle activation/deactivation if needed
136 *
137 * @return void
138 */
139 private function checkVersionAndHandleActivation(): void
140 {
141 if (!function_exists('activate_plugin')) {
142 require_once ABSPATH . 'wp-admin/includes/plugin.php';
143 }
144
145 $settingsService = new SettingsService();
146
147 $currentVersion = IVYFORMS_VERSION;
148 $savedVersion = $settingsService->getSetting('general', 'version');
149
150 if ($savedVersion !== $currentVersion) {
151 deactivate_plugins(IVYFORMS_PLUGIN_SLUG);
152 activate_plugin(IVYFORMS_PLUGIN_SLUG);
153
154 $settingsService->setSetting('general', 'version', $currentVersion);
155 }
156 }
157
158 /**
159 * Remove admin notices on IvyForms admin pages
160 *
161 * @return void
162 */
163 public function removeAdminNotices(): void
164 {
165 // Check if we're on an IvyForms admin page
166 if ($this->isIvyFormsAdminPage()) {
167 // Remove all admin notices
168 remove_all_actions('admin_notices');
169 remove_all_actions('all_admin_notices');
170 // For plugins using user_admin_notices or network_admin_notices
171 remove_all_actions('user_admin_notices');
172 remove_all_actions('network_admin_notices');
173 wp_register_style(
174 'ivyforms_admin_global',
175 IVYFORMS_URL . 'frontend/assets/css/global-admin.css',
176 array(),
177 IVYFORMS_VERSION
178 );
179 wp_enqueue_style('ivyforms_admin_global');
180 }
181 }
182
183 /**
184 * Check if current page is an IvyForms admin page
185 *
186 * @SuppressWarnings(PHPMD)
187 *
188 * @return bool
189 */
190 private function isIvyFormsAdminPage(): bool
191 {
192 if (!is_admin()) {
193 return false;
194 }
195 // Adjust this based on your page's actual slug/identifier
196 return (isset($_GET['page']) && strpos($_GET['page'], 'ivyforms') !== false);
197 }
198
199 /**
200 * Add admin body class
201 *
202 * @param string $classes
203 * @return string
204 */
205 public function addAdminBodyClass(string $classes): string
206 {
207 if ($this->settingsService === null) {
208 return $classes;
209 }
210
211 if ($this->settingsService->getSetting('general', 'fullscreen')) {
212 $classes .= ' ivyforms-fullscreen-mode ';
213 }
214
215 return $classes;
216 }
217 }
218