File: //proc/self/cwd/wp-content/plugins/tutor/components/ConfirmationModal.php
<?php
/**
* Tutor Component: Confirmation Modal
*
* Provides a reusable confirmation modal with Alpine.js integration.
*
* @package Tutor\Components
* @author Themeum
* @link https://themeum.com
* @since 4.0.0
*/
namespace Tutor\Components;
use TUTOR\Icon;
defined( 'ABSPATH' ) || exit;
/**
* Confirmation Modal Component Class.
*
* ```
* // Example usage:
*
* ConfirmationModal::make()
* ->id( 'delete-course-modal' )
* ->title( 'Delete This Course?' )
* ->message( 'Are you sure you want to delete this course permanently? Please confirm your choice.' )
* ->confirm_handler( 'handleDeleteCourse(payload?.courseId)' )
* ->mutation_state( 'deleteMutation' )
* ->render();
*
* // With custom icon
* ConfirmationModal::make()
* ->id( 'delete-announcement-modal' )
* ->title( 'Delete This Announcement?' )
* ->message( 'This action cannot be undone.' )
* ->icon( Icon::DELETE_2, 80 )
* ->confirm_handler( 'handleDeleteAnnouncement(payload?.announcementId)' )
* ->render();
* ```
*
* @since 4.0.0
*/
class ConfirmationModal extends BaseComponent {
const ICON_TYPE_HTML = 'html';
/**
* Modal unique ID.
*
* @since 4.0.0
*
* @var string
*/
protected $id = '';
/**
* Modal title.
*
* @since 4.0.0
*
* @var string
*/
protected $title;
/**
* Confirmation message.
*
* @since 4.0.0
*
* @var string
*/
protected $message;
/**
* Allowed HTML tags and attributes. Keys are tag names and values are allowed attributes.
*
* @since 4.0.0
*
* @var array
*/
protected $allowed_html_tags = array(
'span' => array(
'class' => true,
'x-text' => true,
),
'b' => array(),
'strong' => array(),
'i' => array(),
'em' => array(),
'br' => array(),
);
/**
* Icon name from Icon class.
*
* @since 4.0.0
*
* @var string
*/
protected $icon = '';
/**
* Icon width.
*
* @since 4.0.0
*
* @var int
*/
protected $icon_width = 100;
/**
* Icon height.
*
* @since 4.0.0
*
* @var int
*/
protected $icon_height = 100;
/**
* Icon type.
*
* @since 4.0.0
*
* @var string|null
*/
protected $icon_type = null;
/**
* Confirm handler function name (Alpine.js method).
*
* @since 4.0.0
*
* @var string
*/
protected $confirm_handler = '';
/**
* Mutation state variable name (e.g., 'deleteMutation').
*
* @since 4.0.0
*
* @var string
*/
protected $mutation_state = 'confirmMutation';
/**
* Cancel button text.
*
* @since 4.0.0
*
* @var string
*/
protected $cancel_text = '';
/**
* Confirm button text.
*
* @since 4.0.0
*
* @var string
*/
protected $confirm_text = '';
/**
* Custom width for modal content.
*
* @since 4.0.0
*
* @var string
*/
protected $width = '426px';
/**
* Custom confirm button HTML.
*
* @since 4.0.0
*
* @var string
*/
protected $confirm_btn = '';
/**
* Custom cancel button HTML.
*
* @since 4.0.0
*
* @var string
*/
protected $cancel_btn = '';
/**
* Set modal ID.
*
* @since 4.0.0
*
* @param string $id Modal unique ID.
*
* @return $this
*/
public function id( $id ) {
$this->id = sanitize_key( $id );
return $this;
}
/**
* Set modal title.
*
* @since 4.0.0
*
* @param string $title Modal title.
*
* @return $this
*/
public function title( string $title ) {
$this->title = $title;
return $this;
}
/**
* Sets the confirmation message.
*
* @since 4.0.0
*
* @param string $message The confirmation message text.
* @param array $allowed_html_tags Optional. Allowed HTML tags and attributes. Keys are tag names and values are allowed attributes.
*
* @return $this
*/
public function message( string $message, array $allowed_html_tags = array() ) {
$this->message = $message;
$this->allowed_html_tags = wp_parse_args( $allowed_html_tags, $this->allowed_html_tags );
return $this;
}
/**
* Set icon.
*
* @since 4.0.0
*
* @param string $icon Icon name from Icon class.
* @param int $width Icon width.
* @param int $height Icon height.
* @param string $type Icon type.
*
* @return $this
*/
public function icon( string $icon, int $width = 100, int $height = 100, $type = null ) {
$this->icon = $icon;
$this->icon_width = $width;
$this->icon_height = $height;
$this->icon_type = $type;
return $this;
}
/**
* Set confirm handler function name.
*
* @since 4.0.0
*
* @param string $handler Alpine.js method name.
*
* @return $this
*/
public function confirm_handler( string $handler ) {
$this->confirm_handler = $handler;
return $this;
}
/**
* Set mutation state variable name.
*
* @since 4.0.0
*
* @param string $state Mutation state variable name.
*
* @return $this
*/
public function mutation_state( string $state ) {
$this->mutation_state = $state;
return $this;
}
/**
* Set cancel button text.
*
* @since 4.0.0
*
* @param string $text Cancel button text.
*
* @return $this
*/
public function cancel_text( string $text ) {
$this->cancel_text = $text;
return $this;
}
/**
* Set confirm button text.
*
* @since 4.0.0
*
* @param string $text Confirm button text.
*
* @return $this
*/
public function confirm_text( string $text ) {
$this->confirm_text = $text;
return $this;
}
/**
* Set custom width for modal content.
*
* @since 4.0.0
*
* @param string $width Width value (e.g., '426px', '50%').
*
* @return $this
*/
public function width( string $width ) {
$this->width = $width;
return $this;
}
/**
* Set custom confirm button HTML.
*
* @since 4.0.0
*
* @param string $html Button HTML.
*
* @return $this
*/
public function confirm_button( string $html ) {
$this->confirm_btn = $html;
return $this;
}
/**
* Set custom cancel button HTML.
*
* @since 4.0.0
*
* @param string $html Button HTML.
*
* @return $this
*/
public function cancel_button( string $html ) {
$this->cancel_btn = $html;
return $this;
}
/**
* Get the modal HTML.
*
* @since 4.0.0
*
* @return string HTML output.
*/
public function get(): string {
if ( empty( $this->id ) ) {
return '';
}
if ( empty( $this->icon ) ) {
$this->icon = tutor_utils()->get_themed_svg( 'images/illustrations/delete.svg' );
$this->icon_type = self::ICON_TYPE_HTML;
}
// Set default button texts if not provided.
if ( empty( $this->cancel_text ) ) {
$this->cancel_text = __( 'Cancel', 'tutor' );
}
if ( empty( $this->confirm_text ) ) {
$this->confirm_text = __( 'Yes', 'tutor' );
}
// Build Alpine.js x-data.
$alpine_data = array( 'id' => $this->id );
$alpine_json = wp_json_encode( $alpine_data );
// Build style attribute for custom width.
$style_attr = $this->width
? sprintf( ' style="max-width: %s;"', esc_attr( $this->width ) )
: '';
// Build icon HTML.
$icon_html = '';
if ( ! empty( $this->icon ) ) {
if ( self::ICON_TYPE_HTML === $this->icon_type ) {
$icon_html = $this->icon;
} elseif ( filter_var( $this->icon, FILTER_VALIDATE_URL ) !== false ) {
$icon_html = sprintf( '<img src="%s" style="width:%spx;height:%spx;"/>', $this->icon, $this->icon_width, $this->icon_height );
} else {
ob_start();
SvgIcon::make()->name( $this->icon )->width( $this->icon_width )->height( $this->icon_height )->render();
$icon_html = ob_get_clean();
}
}
// Prepare message HTML with allowed HTML tags.
$message_html = wp_kses( $this->message ?? __( 'Are you sure you want to perform this action? Please confirm your choice.', 'tutor' ), $this->allowed_html_tags );
// Prepare confirm button HTML.
$confirm_html = $this->confirm_btn;
if ( empty( $confirm_html ) ) {
$confirm_html = sprintf(
'<button
class="tutor-btn tutor-btn-destructive tutor-btn-small"
:class="%s?.isPending ? \'tutor-btn-loading\' : \'\'"
@click="%s"
:disabled="%s?.isPending"
>
%s
</button>',
esc_js( $this->mutation_state ),
$this->confirm_handler,
esc_js( $this->mutation_state ),
esc_html( $this->confirm_text )
);
}
// Prepare cancel button HTML.
$cancel_html = $this->cancel_btn;
if ( empty( $cancel_html ) ) {
$cancel_html = sprintf(
'<button
class="tutor-btn tutor-btn-secondary tutor-btn-small"
@click="TutorCore.modal.closeModal(\'%s\')"
>
%s
</button>',
esc_js( $this->id ),
esc_html( $this->cancel_text )
);
}
$this->component_string = sprintf(
'<div x-data="tutorModal(%s)" x-cloak style="display: none;">
<template x-teleport="body">
<div x-bind="getModalBindings()">
<div x-bind="getBackdropBindings()"></div>
<div x-bind="getModalContentBindings()"%s>
<button x-data="tutorIcon({ name: \'cross\', width: 16, height: 16})" x-bind="getCloseButtonBindings()" aria-label="%s"></button>
<div class="tutor-p-7 tutor-pt-10 tutor-flex tutor-flex-column tutor-items-center">
%s
<h5 class="tutor-h5 tutor-font-medium tutor-mt-7">
%s
</h5>
<p class="tutor-p3 tutor-text-secondary tutor-mt-2 tutor-text-center">
%s
</p>
</div>
<div class="tutor-grid tutor-grid-cols-2 tutor-gap-4 tutor-px-7 tutor-pb-6">
%s
%s
</div>
</div>
</div>
</template>
</div>',
esc_attr( $alpine_json ),
$style_attr,
esc_attr__( 'Close', 'tutor' ),
$icon_html,
esc_html( $this->title ?? __( 'Are you sure?', 'tutor' ) ),
$message_html,
$cancel_html,
$confirm_html,
);
return $this->component_string;
}
}