PluginProbe
The Innovative Form Builder – IvyForms / 1.5
The Innovative Form Builder – IvyForms v1.5
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.5, at backend/src/Services/Menu/MenuService.php

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