PluginProbe ʕ •ᴥ•ʔ
Tutor LMS – eLearning and online course solution / 4.0.3
Tutor LMS – eLearning and online course solution v4.0.3
4.0.3 4.0.2 4.0.1 4.0.0 3.9.15 3.9.14 3.9.13 3.9.12 3.9.11 trunk 1.0.0 1.0.0-alpha 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.2.0 1.2.1 1.2.11 1.2.12 1.2.13 1.2.20 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 1.7.3 1.7.4 1.7.5 1.7.6 1.7.7 1.7.8 1.7.9 1.8.0 1.8.1 1.8.10 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 1.8.7 1.8.8 1.8.9 1.9.0 1.9.1 1.9.10 1.9.11 1.9.12 1.9.13 1.9.14 1.9.15 1.9.16 1.9.2 1.9.3 1.9.4 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.0.1 2.0.10 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 2.1.0 2.1.1 2.1.10 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.3.0 2.4.0 2.5.0 2.6.0 2.6.1 2.6.2 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 3.0.0 3.0.1 3.0.2 3.1.0 3.2.0 3.2.1 3.2.2 3.2.3 3.3.0 3.3.1 3.4.0 3.4.1 3.4.2 3.5.0 3.6.0 3.6.1 3.6.2 3.6.3 3.6.4 3.7.0 3.7.1 3.7.2 3.7.3 3.7.4 3.8.0 3.8.1 3.8.2 3.8.3 3.9.0 3.9.1 3.9.10 3.9.2 3.9.3 3.9.4 3.9.5 3.9.6 3.9.7 3.9.8 3.9.9
tutor / components / ConfirmationModal.php
tutor / components Last commit date
Constants 3 weeks ago Accordion.php 1 week ago Alert.php 1 week ago AttachmentCard.php 1 week ago Avatar.php 1 week ago Badge.php 1 week ago BaseComponent.php 3 weeks ago Button.php 1 week ago ConfirmationModal.php 1 week ago CourseFilter.php 1 week ago DateFilter.php 1 week ago DropdownFilter.php 1 week ago EmptyState.php 1 week ago FileUploader.php 1 week ago InputField.php 1 week ago Modal.php 1 week ago Nav.php 1 week ago Pagination.php 1 week ago Popover.php 1 week ago PreviewTrigger.php 1 week ago Progress.php 1 week ago SearchFilter.php 1 week ago Sorting.php 1 week ago StarRating.php 1 week ago StarRatingInput.php 1 week ago StatusSelect.php 1 week ago SvgIcon.php 1 week ago Table.php 1 week ago Tabs.php 1 week ago Tooltip.php 1 week ago WPEditor.php 1 week ago
ConfirmationModal.php
522 lines
1 <?php
2 /**
3 * Tutor Component: Confirmation Modal
4 *
5 * Provides a reusable confirmation modal with Alpine.js integration.
6 *
7 * @package Tutor\Components
8 * @author Themeum
9 * @link https://themeum.com
10 * @since 4.0.0
11 */
12
13 namespace Tutor\Components;
14
15 use TUTOR\Icon;
16
17 defined( 'ABSPATH' ) || exit;
18
19 /**
20 * Confirmation Modal Component Class.
21 *
22 * ```
23 * // Basic delete confirmation
24 * ConfirmationModal::make()
25 * ->id( 'delete-course-modal' )
26 * ->title( 'Delete This Course?' )
27 * ->message( 'Are you sure you want to delete this course permanently? Please confirm your choice.' )
28 * ->confirm_handler( 'handleDeleteCourse(payload?.courseId)' )
29 * ->mutation_state( 'deleteMutation' )
30 * ->render();
31 *
32 * // With custom icon (icon name from Icon class)
33 * ConfirmationModal::make()
34 * ->id( 'delete-announcement-modal' )
35 * ->title( 'Delete This Announcement?' )
36 * ->message( 'This action cannot be undone.' )
37 * ->icon( Icon::DELETE_2, 80, 80 )
38 * ->confirm_handler( 'handleDeleteAnnouncement(payload?.announcementId)' )
39 * ->render();
40 *
41 * // With icon as URL (img will be generated)
42 * ConfirmationModal::make()
43 * ->id( 'remove-student-modal' )
44 * ->title( 'Remove Student?' )
45 * ->message( 'The student will lose access to this course.' )
46 * ->icon( 'https://example.com/icons/warning.svg', 100, 100 )
47 * ->render();
48 *
49 * // With custom button text
50 * ConfirmationModal::make()
51 * ->id( 'publish-course-modal' )
52 * ->title( 'Publish Course?' )
53 * ->message( 'The course will be visible to all students.' )
54 * ->cancel_text( 'Not Yet' )
55 * ->confirm_text( 'Publish Now' )
56 * ->confirm_handler( 'publishCourse()' )
57 * ->render();
58 *
59 * // With custom modal width
60 * ConfirmationModal::make()
61 * ->id( 'wide-confirm-modal' )
62 * ->title( 'Reset All Progress?' )
63 * ->message( 'This will permanently reset all student progress records.' )
64 * ->width( '520px' )
65 * ->confirm_handler( 'resetProgress()' )
66 * ->render();
67 *
68 * // With fully custom confirm / cancel buttons
69 * ConfirmationModal::make()
70 * ->id( 'custom-btn-modal' )
71 * ->title( 'Archive Course?' )
72 * ->message( 'The course will be hidden from the catalog.' )
73 * ->confirm_button( '<button class="tutor-btn tutor-btn-warning tutor-btn-small" @click="archiveCourse()">Archive</button>' )
74 * ->cancel_button( '<button class="tutor-btn tutor-btn-ghost tutor-btn-small" @click="TutorCore.modal.closeModal(\'custom-btn-modal\')">Go Back</button>' )
75 * ->render();
76 *
77 * // With inline HTML in the message (allowed tags)
78 * ConfirmationModal::make()
79 * ->id( 'delete-review-modal' )
80 * ->title( 'Delete Review?' )
81 * ->message( 'You are about to delete the review by <strong x-text="payload?.author"></strong>.' )
82 * ->confirm_handler( 'deleteReview(payload?.reviewId)' )
83 * ->render();
84 * ```
85 *
86 * @since 4.0.0
87 */
88 class ConfirmationModal extends BaseComponent {
89 const ICON_TYPE_HTML = 'html';
90
91 /**
92 * Modal unique ID.
93 *
94 * @since 4.0.0
95 *
96 * @var string
97 */
98 protected $id = '';
99
100 /**
101 * Modal title.
102 *
103 * @since 4.0.0
104 *
105 * @var string
106 */
107 protected $title;
108
109 /**
110 * Confirmation message.
111 *
112 * @since 4.0.0
113 *
114 * @var string
115 */
116 protected $message;
117
118 /**
119 * Allowed HTML tags and attributes. Keys are tag names and values are allowed attributes.
120 *
121 * @since 4.0.0
122 *
123 * @var array
124 */
125 protected $allowed_html_tags = array(
126 'span' => array(
127 'class' => true,
128 'x-text' => true,
129 ),
130 'b' => array(),
131 'strong' => array(),
132 'i' => array(),
133 'em' => array(),
134 'br' => array(),
135 );
136
137 /**
138 * Icon name from Icon class.
139 *
140 * @since 4.0.0
141 *
142 * @var string
143 */
144 protected $icon = '';
145
146 /**
147 * Icon width.
148 *
149 * @since 4.0.0
150 *
151 * @var int
152 */
153 protected $icon_width = 100;
154
155 /**
156 * Icon height.
157 *
158 * @since 4.0.0
159 *
160 * @var int
161 */
162 protected $icon_height = 100;
163
164 /**
165 * Icon type.
166 *
167 * @since 4.0.0
168 *
169 * @var string|null
170 */
171 protected $icon_type = null;
172
173 /**
174 * Confirm handler function name (Alpine.js method).
175 *
176 * @since 4.0.0
177 *
178 * @var string
179 */
180 protected $confirm_handler = '';
181
182 /**
183 * Mutation state variable name (e.g., 'deleteMutation').
184 *
185 * @since 4.0.0
186 *
187 * @var string
188 */
189 protected $mutation_state = 'confirmMutation';
190
191 /**
192 * Cancel button text.
193 *
194 * @since 4.0.0
195 *
196 * @var string
197 */
198 protected $cancel_text = '';
199
200 /**
201 * Confirm button text.
202 *
203 * @since 4.0.0
204 *
205 * @var string
206 */
207 protected $confirm_text = '';
208
209 /**
210 * Custom width for modal content.
211 *
212 * @since 4.0.0
213 *
214 * @var string
215 */
216 protected $width = '426px';
217
218 /**
219 * Custom confirm button HTML.
220 *
221 * @since 4.0.0
222 *
223 * @var string
224 */
225 protected $confirm_btn = '';
226
227 /**
228 * Custom cancel button HTML.
229 *
230 * @since 4.0.0
231 *
232 * @var string
233 */
234 protected $cancel_btn = '';
235
236 /**
237 * Set modal ID.
238 *
239 * @since 4.0.0
240 *
241 * @param string $id Modal unique ID.
242 *
243 * @return $this
244 */
245 public function id( $id ) {
246 $this->id = sanitize_key( $id );
247 return $this;
248 }
249
250 /**
251 * Set modal title.
252 *
253 * @since 4.0.0
254 *
255 * @param string $title Modal title.
256 *
257 * @return $this
258 */
259 public function title( string $title ) {
260 $this->title = $title;
261 return $this;
262 }
263
264 /**
265 * Sets the confirmation message.
266 *
267 * @since 4.0.0
268 *
269 * @param string $message The confirmation message text.
270 * @param array $allowed_html_tags Optional. Allowed HTML tags and attributes. Keys are tag names and values are allowed attributes.
271 *
272 * @return $this
273 */
274 public function message( string $message, array $allowed_html_tags = array() ) {
275 $this->message = $message;
276 $this->allowed_html_tags = wp_parse_args( $allowed_html_tags, $this->allowed_html_tags );
277 return $this;
278 }
279
280 /**
281 * Set icon.
282 *
283 * @since 4.0.0
284 *
285 * @param string $icon Icon name from Icon class.
286 * @param int $width Icon width.
287 * @param int $height Icon height.
288 * @param string $type Icon type.
289 *
290 * @return $this
291 */
292 public function icon( string $icon, int $width = 100, int $height = 100, $type = null ) {
293 $this->icon = $icon;
294 $this->icon_width = $width;
295 $this->icon_height = $height;
296 $this->icon_type = $type;
297 return $this;
298 }
299
300 /**
301 * Set confirm handler function name.
302 *
303 * @since 4.0.0
304 *
305 * @param string $handler Alpine.js method name.
306 *
307 * @return $this
308 */
309 public function confirm_handler( string $handler ) {
310 $this->confirm_handler = $handler;
311 return $this;
312 }
313
314 /**
315 * Set mutation state variable name.
316 *
317 * @since 4.0.0
318 *
319 * @param string $state Mutation state variable name.
320 *
321 * @return $this
322 */
323 public function mutation_state( string $state ) {
324 $this->mutation_state = $state;
325 return $this;
326 }
327
328 /**
329 * Set cancel button text.
330 *
331 * @since 4.0.0
332 *
333 * @param string $text Cancel button text.
334 *
335 * @return $this
336 */
337 public function cancel_text( string $text ) {
338 $this->cancel_text = $text;
339 return $this;
340 }
341
342 /**
343 * Set confirm button text.
344 *
345 * @since 4.0.0
346 *
347 * @param string $text Confirm button text.
348 *
349 * @return $this
350 */
351 public function confirm_text( string $text ) {
352 $this->confirm_text = $text;
353 return $this;
354 }
355
356 /**
357 * Set custom width for modal content.
358 *
359 * @since 4.0.0
360 *
361 * @param string $width Width value (e.g., '426px', '50%').
362 *
363 * @return $this
364 */
365 public function width( string $width ) {
366 $this->width = $width;
367 return $this;
368 }
369
370 /**
371 * Set custom confirm button HTML.
372 *
373 * @since 4.0.0
374 *
375 * @param string $html Button HTML.
376 *
377 * @return $this
378 */
379 public function confirm_button( string $html ) {
380 $this->confirm_btn = $html;
381 return $this;
382 }
383
384 /**
385 * Set custom cancel button HTML.
386 *
387 * @since 4.0.0
388 *
389 * @param string $html Button HTML.
390 *
391 * @return $this
392 */
393 public function cancel_button( string $html ) {
394 $this->cancel_btn = $html;
395 return $this;
396 }
397
398 /**
399 * Get the modal HTML.
400 *
401 * @since 4.0.0
402 *
403 * @return string HTML output.
404 */
405 public function get(): string {
406 if ( empty( $this->id ) ) {
407 return '';
408 }
409
410 if ( empty( $this->icon ) ) {
411 $this->icon = tutor_utils()->get_themed_svg( 'images/illustrations/delete.svg' );
412 $this->icon_type = self::ICON_TYPE_HTML;
413 }
414
415 // Set default button texts if not provided.
416 if ( empty( $this->cancel_text ) ) {
417 $this->cancel_text = __( 'Cancel', 'tutor' );
418 }
419 if ( empty( $this->confirm_text ) ) {
420 $this->confirm_text = __( 'Yes', 'tutor' );
421 }
422
423 // Build Alpine.js x-data.
424 $alpine_data = array( 'id' => $this->id );
425 $alpine_json = wp_json_encode( $alpine_data );
426
427 // Build style attribute for custom width.
428 $style_attr = $this->width
429 ? sprintf( ' style="max-width: %s;"', esc_attr( $this->width ) )
430 : '';
431
432 // Build icon HTML.
433 $icon_html = '';
434 if ( ! empty( $this->icon ) ) {
435 if ( self::ICON_TYPE_HTML === $this->icon_type ) {
436 $icon_html = $this->icon;
437 } elseif ( filter_var( $this->icon, FILTER_VALIDATE_URL ) !== false ) {
438 $icon_html = sprintf( '<img src="%s" style="width:%spx;height:%spx;"/>', $this->icon, $this->icon_width, $this->icon_height );
439 } else {
440 ob_start();
441 SvgIcon::make()->name( $this->icon )->width( $this->icon_width )->height( $this->icon_height )->render();
442 $icon_html = ob_get_clean();
443 }
444 }
445
446 // Prepare message HTML with allowed HTML tags.
447 $message_html = wp_kses( $this->message ?? __( 'Are you sure you want to perform this action? Please confirm your choice.', 'tutor' ), $this->allowed_html_tags );
448
449 // Prepare confirm button HTML.
450 $confirm_html = $this->confirm_btn;
451 if ( empty( $confirm_html ) ) {
452 $confirm_html = sprintf(
453 '<button
454 class="tutor-btn tutor-btn-destructive tutor-btn-small"
455 :class="%s?.isPending ? \'tutor-btn-loading\' : \'\'"
456 @click="%s"
457 :disabled="%s?.isPending"
458 >
459 %s
460 </button>',
461 esc_js( $this->mutation_state ),
462 $this->confirm_handler,
463 esc_js( $this->mutation_state ),
464 esc_html( $this->confirm_text )
465 );
466 }
467
468 // Prepare cancel button HTML.
469 $cancel_html = $this->cancel_btn;
470 if ( empty( $cancel_html ) ) {
471 $cancel_html = sprintf(
472 '<button
473 class="tutor-btn tutor-btn-secondary tutor-btn-small"
474 @click="TutorCore.modal.closeModal(\'%s\')"
475 >
476 %s
477 </button>',
478 esc_js( $this->id ),
479 esc_html( $this->cancel_text )
480 );
481 }
482
483 $this->component_string = sprintf(
484 '<div x-data="tutorModal(%s)" x-cloak style="display: none;">
485 <template x-teleport="body">
486 <div x-bind="getModalBindings()">
487 <div x-bind="getBackdropBindings()"></div>
488 <div x-bind="getModalContentBindings()"%s>
489 <button x-data="tutorIcon({ name: \'cross\', width: 16, height: 16})" x-bind="getCloseButtonBindings()" aria-label="%s"></button>
490
491 <div class="tutor-p-7 tutor-pt-10 tutor-flex tutor-flex-column tutor-items-center">
492 %s
493 <h5 class="tutor-h5 tutor-font-medium tutor-mt-7">
494 %s
495 </h5>
496 <p class="tutor-p3 tutor-text-secondary tutor-mt-2 tutor-text-center">
497 %s
498 </p>
499 </div>
500
501 <div class="tutor-grid tutor-grid-cols-2 tutor-gap-4 tutor-px-7 tutor-pb-6">
502 %s
503 %s
504 </div>
505 </div>
506 </div>
507 </template>
508 </div>',
509 esc_attr( $alpine_json ),
510 $style_attr,
511 esc_attr__( 'Close', 'tutor' ),
512 $icon_html,
513 esc_html( $this->title ?? __( 'Are you sure?', 'tutor' ) ),
514 $message_html,
515 $cancel_html,
516 $confirm_html,
517 );
518
519 return $this->component_string;
520 }
521 }
522