PluginProbe
SureForms – Contact Form Builder, AI Forms, Payment Form, Survey & Quiz / 2.11.1
SureForms – Contact Form Builder, AI Forms, Payment Form, Survey & Quiz v2.11.1
2.12.6 2.12.5 2.12.4 2.12.3 2.12.2 2.12.1 2.12.0 2.11.1 2.11.0 2.10.1 2.10.0 2.9.1 2.9.0 2.8.2 2.8.1 2.7.0 2.7.1 2.8.0 trunk 0.0.10 0.0.11 0.0.12 0.0.13 0.0.2 0.0.3 All 96 releases
sureforms / inc / learn.php
learn.php
440 lines 13.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * SureForms Learn Helper Class
4 *
5 * @package sureforms
6 * @since 2.5.2
7 */
8
9 namespace SRFM\Inc;
10
11 use SRFM\Inc\Traits\Get_Instance;
12
13 if ( ! defined( 'ABSPATH' ) ) {
14 exit; // Exit if accessed directly.
15 }
16
17 /**
18 * Learn class.
19 *
20 * @since 2.5.2
21 */
22 class Learn {
23 use Get_Instance;
24
25 /**
26 * Constructor.
27 *
28 * @since 2.5.2
29 */
30 public function __construct() {
31 add_action( 'rest_api_init', [ $this, 'register_rest_routes' ] );
32 }
33
34 /**
35 * Get default learn modules structure.
36 *
37 * Returns the complete structure of all available modules and their lessons.
38 * This serves as the source of truth for module definitions used across
39 * the plugin for both frontend display and analytics validation.
40 *
41 * @return array Array of module objects with their lessons.
42 * @since 2.5.2
43 */
44 public static function get_chapters_structure() {
45 $chapters = [
46 [
47 'id' => 'setting-up-form',
48 'title' => __( 'Setting Up Your Form', 'sureforms' ),
49 'description' => __( 'Get started with SureForms by building your first form, adding the right fields, and styling it to match your brand.', 'sureforms' ),
50 'url' => 'https://sureforms.com/docs/creating-and-publishing-forms/',
51 'steps' => [
52 [
53 'id' => 'creating-first-form',
54 'title' => __( 'Creating Your First Form', 'sureforms' ),
55 'description' => __( 'Creating a form with SureForms takes just a few minutes. Just describe the kind of form you need in a simple prompt, and let SureForms AI handle the heavy lifting for you.', 'sureforms' ),
56 'learn' => [
57 'type' => 'dialog',
58 'content' => [
59 'type' => 'gif-video',
60 'data' => [
61 'url' => 'https://www.youtube.com/embed/pMWZ2ko3G1k',
62 'alt' => __( 'Creating Your First Form', 'sureforms' ),
63 ],
64 ],
65 ],
66 'docsUrl' => 'https://sureforms.com/docs/creating-and-publishing-forms/',
67 'headerAction' => [
68 'label' => __( 'Create a Form', 'sureforms' ),
69 'url' => 'admin.php?page=add-new-form&source=learn',
70 ],
71 'completed' => false,
72 ],
73 [
74 'id' => 'set-up-form-fields',
75 'title' => __( 'Set Up Your Form Fields', 'sureforms' ),
76 'description' => __( 'Adjust the field settings according to your requirements.', 'sureforms' ),
77 'learn' => [
78 'type' => 'dialog',
79 'content' => [
80 'type' => 'gif-video',
81 'data' => [
82 'url' => 'https://www.youtube.com/embed/uQchuO6kMeY',
83 'alt' => __( 'Set Up Your Form Fields', 'sureforms' ),
84 ],
85 ],
86 ],
87 'docsUrl' => 'https://sureforms.com/docs/',
88 'headerAction' => [
89 'label' => __( 'Set Up Fields', 'sureforms' ),
90 'url' => 'post-new.php?post_type=sureforms_form',
91 'dynamic' => 'latest-form',
92 'source' => 'learn-setup-fields',
93 ],
94 'completed' => false,
95 ],
96 [
97 'id' => 'style-your-forms',
98 'title' => __( 'Style Your Forms', 'sureforms' ),
99 'description' => __( 'Customize the look and feel of your form to match your brand. Adjust background, colors, layout and etc. to create a seamless experience for your visitors.', 'sureforms' ),
100 'learn' => [
101 'type' => 'dialog',
102 'content' => [
103 'type' => 'gif-video',
104 'data' => [
105 'url' => 'https://www.youtube.com/embed/n8JnocyZ3i4',
106 'alt' => __( 'Style Your Forms', 'sureforms' ),
107 ],
108 ],
109 ],
110 'docsUrl' => 'https://sureforms.com/docs/',
111 'headerAction' => [
112 'label' => __( 'Style Form', 'sureforms' ),
113 'url' => 'post-new.php?post_type=sureforms_form&source=learn-style-form',
114 'dynamic' => 'latest-form',
115 'source' => 'learn-style-form',
116 ],
117 'completed' => false,
118 ],
119 ],
120 ],
121 [
122 'id' => 'making-form-live',
123 'title' => __( 'Making Your Form Live', 'sureforms' ),
124 'description' => __( 'Publish your form and make it accessible to your visitors using Instant Form or by embedding it on any page.', 'sureforms' ),
125 'url' => 'https://sureforms.com/docs/instant-forms/',
126 'steps' => [
127 [
128 'id' => 'instant-form',
129 'title' => __( 'Instant Form', 'sureforms' ),
130 'description' => __( 'No need to design a separate page just for the forms. Publish your form instantly on a dedicated landing page. Just enable Instant Form option and share the link.', 'sureforms' ),
131 'learn' => [
132 'type' => 'dialog',
133 'content' => [
134 'type' => 'gif-video',
135 'data' => [
136 'url' => 'https://www.youtube.com/embed/SyFYazEjJNA',
137 'alt' => __( 'Instant Form', 'sureforms' ),
138 ],
139 ],
140 ],
141 'docsUrl' => 'https://sureforms.com/docs/',
142 'headerAction' => [
143 'label' => __( 'Instant Form', 'sureforms' ),
144 'url' => 'post-new.php?post_type=sureforms_form&source=learn-instant-form',
145 'dynamic' => 'latest-form',
146 'source' => 'learn-instant-form',
147 ],
148 'completed' => false,
149 ],
150 [
151 'id' => 'embed-forms',
152 'title' => __( 'Embed Your Forms in a Page', 'sureforms' ),
153 'description' => __( 'Easily embed your form on any page using the built-in SureForms block.', 'sureforms' ),
154 'learn' => [
155 'type' => 'dialog',
156 'content' => [
157 'type' => 'gif-video',
158 'data' => [
159 'url' => 'https://www.youtube.com/embed/vldMwp7rquM',
160 'alt' => __( 'Embed Your Forms in a Page', 'sureforms' ),
161 ],
162 ],
163 ],
164 'docsUrl' => 'https://sureforms.com/docs/displaying-forms/',
165 'headerAction' => [
166 'label' => __( 'Embed Forms', 'sureforms' ),
167 'url' => self::get_embed_forms_url(),
168 ],
169 'completed' => false,
170 ],
171 ],
172 ],
173 [
174 'id' => 'managing-entries',
175 'title' => __( 'Managing Entries', 'sureforms' ),
176 'description' => __( 'Stay on top of your form submissions with email notifications and the built-in entries manager.', 'sureforms' ),
177 'url' => 'https://sureforms.com/docs/adjust-form-notification-emails/',
178 'steps' => [
179 [
180 'id' => 'email-notification',
181 'title' => __( 'Email Notifications', 'sureforms' ),
182 'description' => __( 'Get email notifications whenever someone fills out your form.', 'sureforms' ),
183 'learn' => [
184 'type' => 'dialog',
185 'content' => [
186 'type' => 'gif-video',
187 'data' => [
188 'url' => 'https://www.youtube.com/embed/tvlGvgUZrhM',
189 'alt' => __( 'Configure Your Email Notification', 'sureforms' ),
190 ],
191 ],
192 ],
193 'docsUrl' => 'https://sureforms.com/docs/adjust-form-notification-emails/',
194 'headerAction' => [
195 'label' => __( 'Configure', 'sureforms' ),
196 'url' => 'admin.php?page=sureforms_form_settings&tab=general-settings&source=learn',
197 ],
198 'completed' => false,
199 ],
200 [
201 'id' => 'manage-entries',
202 'title' => __( 'Manage Entries', 'sureforms' ),
203 'description' => __( 'View, filter, and manage all form submissions from one place. Export entries, delete spam, and keep your data organized with the SureForms Entries manager.', 'sureforms' ),
204 'learn' => [
205 'type' => 'dialog',
206 'content' => [
207 'type' => 'gif-video',
208 'data' => [
209 'url' => 'https://www.youtube.com/embed/8ycIcYvS--M',
210 'alt' => __( 'Manage Entries', 'sureforms' ),
211 ],
212 ],
213 ],
214 'docsUrl' => 'https://sureforms.com/docs/',
215 'headerAction' => [
216 'label' => __( 'Go to Entries', 'sureforms' ),
217 'url' => 'admin.php?page=sureforms_entries&source=learn',
218 ],
219 'completed' => false,
220 ],
221 ],
222 ],
223 ];
224
225 /**
226 * Filter learn chapters structure.
227 *
228 * @param array $chapters Learn chapters data.
229 * @since 2.5.2
230 */
231 return apply_filters( 'srfm_learn_chapters', $chapters );
232 }
233
234 /**
235 * Get the edit URL for an existing page to use for the "Embed Forms" lesson.
236 *
237 * Finds the "Sample Page" (default WordPress page) or falls back to the
238 * most recent published page. If no pages exist, falls back to creating a new page.
239 *
240 * @return string The admin edit URL for the page.
241 * @since 2.5.2
242 */
243 public static function get_embed_forms_url() {
244 // Try to find the default "Sample Page" by slug.
245 $sample_page = get_page_by_path( 'sample-page' );
246
247 if ( $sample_page ) {
248 return 'post.php?post=' . $sample_page->ID . '&action=edit&source=learn';
249 }
250
251 // Fallback: get the most recent published page.
252 $pages = get_pages(
253 [
254 'sort_column' => 'post_date',
255 'sort_order' => 'DESC',
256 'number' => 1,
257 ]
258 );
259
260 if ( ! empty( $pages ) ) {
261 return 'post.php?post=' . $pages[0]->ID . '&action=edit&source=learn';
262 }
263
264 // Last fallback: create a new page.
265 return 'post-new.php?post_type=page&source=learn';
266 }
267
268 /**
269 * Get learn chapters with user progress merged.
270 *
271 * @param int $user_id Optional. User ID to get progress for. Defaults to current user.
272 * @return array Chapters array with progress data merged.
273 * @since 2.5.2
274 */
275 public static function get_learn_chapters( $user_id = 0 ) {
276 if ( ! $user_id ) {
277 $user_id = get_current_user_id();
278 }
279
280 // Get chapters structure.
281 $chapters = self::get_chapters_structure();
282
283 // Get saved progress from user meta.
284 $saved_progress = get_user_meta( $user_id, 'srfm_learn_progress', true );
285 if ( ! is_array( $saved_progress ) ) {
286 $saved_progress = [];
287 }
288
289 // Merge saved progress with chapters.
290 foreach ( $chapters as &$chapter ) {
291 // Validate chapter structure.
292 if ( ! isset( $chapter['id'], $chapter['steps'] ) || ! is_array( $chapter['steps'] ) ) {
293 continue;
294 }
295
296 $chapter_id = $chapter['id'];
297
298 foreach ( $chapter['steps'] as &$step ) {
299 if ( ! isset( $step['id'] ) ) {
300 continue;
301 }
302
303 $step_id = $step['id'];
304 if ( isset( $saved_progress[ $chapter_id ][ $step_id ] ) ) {
305 $step['completed'] = Helper::get_boolean_value( $saved_progress[ $chapter_id ][ $step_id ] );
306 }
307 }
308 }
309
310 return $chapters;
311 }
312
313 /**
314 * Register REST API endpoints for Learn functionality.
315 *
316 * @since 2.5.2
317 * @return void
318 */
319 public function register_rest_routes() {
320 register_rest_route(
321 'sureforms/v1',
322 '/get-learn-chapters',
323 [
324 'methods' => \WP_REST_Server::READABLE,
325 'callback' => [ $this, 'rest_get_learn_chapters' ],
326 'permission_callback' => static function () {
327 return current_user_can( 'manage_options' );
328 },
329 ]
330 );
331
332 register_rest_route(
333 'sureforms/v1',
334 '/update-learn-progress',
335 [
336 'methods' => \WP_REST_Server::CREATABLE,
337 'callback' => [ $this, 'rest_update_learn_progress' ],
338 'permission_callback' => static function () {
339 return current_user_can( 'manage_options' );
340 },
341 'args' => [
342 'chapterId' => [
343 'required' => true,
344 'type' => 'string',
345 'sanitize_callback' => 'sanitize_text_field',
346 ],
347 'stepId' => [
348 'required' => true,
349 'type' => 'string',
350 'sanitize_callback' => 'sanitize_text_field',
351 ],
352 'completed' => [
353 'required' => true,
354 'type' => 'boolean',
355 'sanitize_callback' => 'rest_sanitize_boolean',
356 ],
357 ],
358 ]
359 );
360 }
361
362 /**
363 * REST API callback to get learn chapters with user progress.
364 *
365 * @return \WP_REST_Response Response object.
366 * @since 2.5.2
367 */
368 public function rest_get_learn_chapters() {
369 $user_id = get_current_user_id();
370 $chapters = self::get_learn_chapters( $user_id );
371
372 return rest_ensure_response( $chapters );
373 }
374
375 /**
376 * REST API callback to update learn progress.
377 *
378 * @param \WP_REST_Request $request Request object.
379 * @return \WP_REST_Response|\WP_Error Response object or error.
380 * @since 2.5.2
381 */
382 public function rest_update_learn_progress( $request ) {
383 $chapter_id = $request->get_param( 'chapterId' );
384 $step_id = $request->get_param( 'stepId' );
385 $completed = $request->get_param( 'completed' );
386 $user_id = get_current_user_id();
387
388 // Validate that chapterId and stepId exist in the defined structure.
389 $chapters = self::get_chapters_structure();
390 $valid_step = false;
391
392 foreach ( $chapters as $chapter ) {
393 if ( $chapter['id'] !== $chapter_id ) {
394 continue;
395 }
396 foreach ( $chapter['steps'] as $step ) {
397 if ( $step['id'] === $step_id ) {
398 $valid_step = true;
399 break 2;
400 }
401 }
402 }
403
404 if ( ! $valid_step ) {
405 return new \WP_Error(
406 'invalid_step',
407 __( 'Invalid chapter or step ID.', 'sureforms' ),
408 [ 'status' => 400 ]
409 );
410 }
411
412 // Get current progress.
413 $saved_progress = get_user_meta( $user_id, 'srfm_learn_progress', true );
414 if ( ! is_array( $saved_progress ) ) {
415 $saved_progress = [];
416 }
417
418 // Update progress.
419 if ( ! isset( $saved_progress[ $chapter_id ] ) ) {
420 $saved_progress[ $chapter_id ] = [];
421 }
422 $saved_progress[ $chapter_id ][ $step_id ] = $completed;
423
424 // Save to user meta.
425 update_user_meta( $user_id, 'srfm_learn_progress', $saved_progress );
426
427 // Flag for analytics — next send cycle will include updated learn snapshot.
428 set_transient( 'srfm_learn_progress_changed', 1, 0 );
429
430 return rest_ensure_response(
431 [
432 'success' => true,
433 'chapterId' => $chapter_id,
434 'stepId' => $step_id,
435 'completed' => $completed,
436 ]
437 );
438 }
439 }
440