PluginProbe
The Innovative Form Builder – IvyForms / 1.4
The Innovative Form Builder – IvyForms v1.4
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 / Services / Menu / MenuService.php

MenuService.php in The Innovative Form Builder – IvyForms 1.4, at backend/src/Services/Menu/MenuService.php

261 lines 8.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace IvyForms\Services\Menu;
4
5 use IvyForms\Routes\Routes;
6 use IvyForms\Services\Ai\AiAvailability;
7 use IvyForms\Services\Settings\SettingsService;
8 use IvyForms\Services\Permissions\IvyFormsAccess;
9 use IvyForms\Services\Permissions\RoutePermissionService;
10 use IvyForms\Services\Translations\BackendStrings;
11
12 /**
13 * Renders menu pages
14 */
15 class MenuService
16 {
17 private ?RoutePermissionService $routePermissionService;
18
19 public function __construct(?RoutePermissionService $routePermissionService = null)
20 {
21 $this->routePermissionService = $routePermissionService;
22 }
23
24 /**
25 * Effective IvyForms permissions for the current user, keyed by permission key.
26 *
27 * Exposed to the frontend so the UI can gate actions (hide "+ Form", etc.) to match
28 * the backend permission checks. Backend validation always remains the source of truth.
29 *
30 * @return array<string, bool>
31 */
32 private function currentUserPermissions(): array
33 {
34 $perm = $this->routePermissionService;
35 if ($perm === null) {
36 return [];
37 }
38
39 return [
40 'view_forms_list' => $perm->canViewForms(),
41 'add_edit_forms' => $perm->canEditForms(),
42 'delete_forms' => $perm->canDeleteForms(),
43 'view_entries_admin' => $perm->canViewEntries(),
44 'delete_entries_admin' => $perm->canDeleteEntries(),
45 'access_settings_page' => $perm->canAccessSettings(),
46 ];
47 }
48
49 /**
50 * @return array{available: bool, status: string, actionUrl: string, connectorsUrl: string}
51 */
52 private function currentAiAvailability(): array
53 {
54 $status = AiAvailability::getStatus();
55 $actionUrl = '';
56
57 if ($status === AiAvailability::STATUS_WORDPRESS_UPDATE_REQUIRED) {
58 $actionUrl = AiAvailability::getWordPressUpdateUrl();
59 } elseif ($status === AiAvailability::STATUS_AI_CLIENT_MISSING) {
60 $actionUrl = AiAvailability::getAiPluginInstallUrl();
61 } elseif ($status === AiAvailability::STATUS_TEXT_GENERATION_UNAVAILABLE) {
62 $actionUrl = AiAvailability::getConnectorsSettingsUrl();
63 }
64
65 return [
66 'available' => $status === AiAvailability::STATUS_AVAILABLE,
67 'status' => $status,
68 'actionUrl' => $actionUrl,
69 'connectorsUrl' => AiAvailability::getConnectorsSettingsUrl(),
70 ];
71 }
72
73 /**
74 * Submenu page render function
75 * @param string $page
76 */
77 public function render(string $page): void
78 {
79 $page = trim($page);
80 $scriptId = IVYFORMS_DEV ? 'ivyforms_scripts_dev_vite' : 'ivyforms_script_index';
81 $scriptSrc = IVYFORMS_DEV ?
82 'http://localhost:5173/src/assets/js/admin/admin.ts' :
83 IVYFORMS_URL . 'frontend/dist/admin.js';
84 $styleSrc = IVYFORMS_DEV ? '' : IVYFORMS_URL . 'frontend/dist/index.css';
85 $scriptVersion = IVYFORMS_DEV ? null : IVYFORMS_VERSION;
86
87 wp_enqueue_script(
88 $scriptId,
89 $scriptSrc,
90 [],
91 $scriptVersion,
92 true
93 );
94
95 // TODO: Check including fonts on build
96 // @phpstan-ignore-next-line
97 if ($styleSrc) {
98 wp_enqueue_style(
99 'ivyforms_style_admin',
100 IVYFORMS_URL . 'frontend/dist/admin.css',
101 [],
102 $scriptVersion
103 );
104 wp_enqueue_style(
105 'ivyforms_style_index',
106 $styleSrc,
107 [],
108 $scriptVersion
109 );
110 // wp_enqueue_style(
111 // 'ivyforms_font_roboto_regular_woff2',
112 // IVYFORMS_URL . 'frontend/dist/Roboto-Regular.woff2',
113 // [],
114 // $scriptVersion
115 // );
116 // wp_enqueue_style(
117 // 'ivyforms_font_roboto_regular_woff',
118 // IVYFORMS_URL . 'frontend/dist/Roboto-Regular.woff',
119 // [],
120 // $scriptVersion
121 // );
122 // wp_enqueue_style(
123 // 'ivyforms_font_roboto_medium_woff2',
124 // IVYFORMS_URL . 'frontend/dist/Roboto-Medium.woff2',
125 // [],
126 // $scriptVersion
127 // );
128 // wp_enqueue_style(
129 // 'ivyforms_font_roboto_medium_woff',
130 // IVYFORMS_URL . 'frontend/dist/Roboto-Medium.woff',
131 // [],
132 // $scriptVersion
133 // );
134 // wp_enqueue_style(
135 // 'ivyforms_font_roboto_bold_woff2',
136 // IVYFORMS_URL . 'frontend/dist/Roboto-Bold.woff2',
137 // [],
138 // $scriptVersion
139 // );
140 // wp_enqueue_style(
141 // 'ivyforms_font_roboto_bold_woff',
142 // IVYFORMS_URL . 'frontend/dist/Roboto-Bold.woff',
143 // [],
144 // $scriptVersion
145 // );
146 }
147
148 $this->localizeScripts($scriptId);
149
150 /**
151 * Hook to enqueue additional scripts and styles in admin area
152 * @since 0.1.0
153 *
154 * Arguments:
155 * - string $scriptId The main script handle ID (for dependencies)
156 * - string $page WordPress admin menu slug (e.g. ivyforms-builder)
157 */
158 do_action('ivyforms/admin/enqueue_scripts', $scriptId, $page);
159
160 if ($page === 'ivyforms-builder') {
161 // FormBuilder.vue welcome-page image picker (Pro); not needed on other admin pages
162 wp_enqueue_media();
163 }
164
165 include IVYFORMS_PATH . '/view/backend/view.php';
166 }
167
168 /**
169 * Localize all admin data required by the frontend app.
170 *
171 * @param string $scriptId Main script handle used as the localization target.
172 */
173 private function localizeScripts(string $scriptId): void
174 {
175 $settingsStorage = new SettingsService();
176
177 wp_localize_script(
178 $scriptId,
179 'wpIvySettings',
180 $settingsStorage->getFrontendSettings()
181 );
182
183 $backendLabels = array_merge(
184 BackendStrings::getNewFormStrings(),
185 BackendStrings::getStylesFormBuilderStrings(),
186 BackendStrings::getSettingsFormBuilderStrings(),
187 BackendStrings::getWelcomePageStrings(),
188 BackendStrings::getResultsFormBuilderStrings(),
189 BackendStrings::getEmptyStatesStrings(),
190 BackendStrings::getEntityFormStrings(),
191 BackendStrings::getAllFormsStrings(),
192 BackendStrings::getDashboardStrings(),
193 BackendStrings::getCommonStrings(),
194 BackendStrings::getComponentsStrings(),
195 BackendStrings::getEntriesStrings(),
196 BackendStrings::getIntegrationsStrings(),
197 BackendStrings::getExceptionStrings(),
198 BackendStrings::getTemplateStrings(),
199 BackendStrings::getAiStrings(),
200 BackendStrings::getSettingsStrings(),
201 BackendStrings::getSecurityStrings(),
202 BackendStrings::getPermissionsStrings(),
203 BackendStrings::getProUpgradeDialogStrings(),
204 BackendStrings::getChangelogStrings()
205 );
206
207 /**
208 * Filter backend labels before localizing
209 * Allows Pro version to merge additional strings
210 *
211 * @since 0.1.0
212 * @param array $backendLabels Array of backend label strings
213 */
214 $backendLabels = apply_filters('ivyforms/admin/backend_labels', $backendLabels);
215
216 wp_localize_script(
217 $scriptId,
218 'wpIvyLabels',
219 $backendLabels
220 );
221
222 wp_localize_script(
223 $scriptId,
224 'wpIvyUrls',
225 [
226 'pluginURL' => IVYFORMS_URL,
227 'siteURL' => esc_url_raw(site_url()),
228 ]
229 );
230
231 $aiAvailability = $this->currentAiAvailability();
232
233 wp_localize_script(
234 $scriptId,
235 'wpIvyApiSettings',
236 [
237 'root' => esc_url_raw(rest_url()),
238 'nonce' => wp_create_nonce('wp_rest'),
239 'namespace' => Routes::$routeNamespace,
240 'isAdministrator' => IvyFormsAccess::currentUserCanAccessPermissionsSettings(),
241 'permissions' => $this->currentUserPermissions(),
242 'aiAvailable' => $aiAvailability['available'],
243 'aiStatus' => $aiAvailability['status'],
244 'aiActionUrl' => $aiAvailability['actionUrl'],
245 'aiConnectorsUrl' => $aiAvailability['connectorsUrl'],
246 ]
247 );
248
249 wp_localize_script(
250 $scriptId,
251 'wpIvyDateFormat',
252 [
253 'dateFormat' => get_option('date_format'),
254 'timeFormat' => get_option('time_format'),
255 'dateTimeFormat' => get_option('date_format') . ' ' . get_option('time_format'),
256 'locale' => get_locale(),
257 ]
258 );
259 }
260 }
261