487 lines
No EOL
20 KiB
PHP
487 lines
No EOL
20 KiB
PHP
<?php
|
|
|
|
namespace Quiztech\AssessmentPlatform\Admin;
|
|
|
|
/**
|
|
* Handles the Quiztech plugin settings page in WP Admin.
|
|
*/
|
|
class SettingsPage {
|
|
|
|
/**
|
|
* Option group name.
|
|
* @var string
|
|
*/
|
|
private $option_group = 'quiztech_settings';
|
|
|
|
/**
|
|
* Option name in wp_options table.
|
|
* @var string
|
|
*/
|
|
private $option_name = 'quiztech_settings';
|
|
|
|
/**
|
|
* Settings page slug.
|
|
* @var string
|
|
*/
|
|
private $page_slug = 'quiztech-settings-page';
|
|
|
|
/**
|
|
* Register hooks for the settings page.
|
|
*/
|
|
public function register_hooks() {
|
|
add_action( 'admin_menu', [ $this, 'add_admin_page' ] );
|
|
add_action( 'admin_init', [ $this, 'register_settings' ] );
|
|
add_action( 'wp_ajax_quiztech_send_test_email', [ $this, 'handle_send_test_email_ajax' ] );
|
|
}
|
|
|
|
/**
|
|
* Adds the submenu page under the main Settings menu.
|
|
*/
|
|
public function add_admin_page() {
|
|
add_options_page(
|
|
__( 'Quiztech Settings', 'quiztech' ), // Page Title
|
|
__( 'Quiztech', 'quiztech' ), // Menu Title
|
|
'manage_options', // Capability Required
|
|
$this->page_slug, // Menu Slug
|
|
[ $this, 'render_settings_page' ] // Callback function to render the page
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Registers settings, sections, and fields using the Settings API.
|
|
*/
|
|
public function register_settings() {
|
|
register_setting(
|
|
$this->option_group, // Option group
|
|
$this->option_name, // Option name
|
|
[ $this, 'sanitize_settings' ] // Sanitization callback
|
|
);
|
|
|
|
// Stripe Section
|
|
add_settings_section(
|
|
'quiztech_stripe_section', // Section ID
|
|
__( 'Stripe API Keys', 'quiztech' ), // Section Title
|
|
'__return_false', // Section callback (optional description)
|
|
$this->page_slug // Page slug where section appears
|
|
);
|
|
|
|
// Stripe Public Key Field
|
|
add_settings_field(
|
|
'quiztech_stripe_public_key', // Field ID
|
|
__( 'Stripe Public Key', 'quiztech' ), // Field Title
|
|
[ $this, 'render_text_field' ], // Field render callback
|
|
$this->page_slug, // Page slug
|
|
'quiztech_stripe_section', // Section ID
|
|
[ // Arguments for callback
|
|
'id' => 'quiztech_stripe_public_key',
|
|
'option_name' => $this->option_name,
|
|
'key' => 'stripe_public_key',
|
|
'description' => __( 'Enter your Stripe publishable API key.', 'quiztech' )
|
|
]
|
|
);
|
|
|
|
// Stripe Secret Key Field
|
|
add_settings_field(
|
|
'quiztech_stripe_secret_key', // Field ID
|
|
__( 'Stripe Secret Key', 'quiztech' ), // Field Title
|
|
[ $this, 'render_text_field' ], // Field render callback
|
|
$this->page_slug, // Page slug
|
|
'quiztech_stripe_section', // Section ID
|
|
[ // Arguments for callback
|
|
'id' => 'quiztech_stripe_secret_key',
|
|
'option_name' => $this->option_name,
|
|
'key' => 'stripe_secret_key',
|
|
'type' => 'password', // Mask the input
|
|
'description' => __( 'Enter your Stripe secret API key. This is kept confidential.', 'quiztech' )
|
|
]
|
|
);
|
|
|
|
|
|
// --- SMTP Section ---
|
|
add_settings_section(
|
|
'quiztech_smtp_section', // Section ID
|
|
__( 'SMTP Settings', 'quiztech' ), // Section Title
|
|
[ $this, 'render_smtp_section_description' ], // Section callback for description
|
|
$this->page_slug // Page slug where section appears
|
|
);
|
|
|
|
// SMTP Enabled Field (Checkbox)
|
|
add_settings_field(
|
|
'quiztech_smtp_enabled',
|
|
__( 'Enable SMTP', 'quiztech' ),
|
|
[ $this, 'render_checkbox_field' ], // New callback needed
|
|
$this->page_slug,
|
|
'quiztech_smtp_section',
|
|
[
|
|
'id' => 'quiztech_smtp_enabled',
|
|
'option_name' => $this->option_name,
|
|
'key' => 'smtp_enabled',
|
|
'description' => __( 'Enable sending emails via a custom SMTP server instead of the default WordPress mail function.', 'quiztech' )
|
|
]
|
|
);
|
|
|
|
// SMTP Host Field
|
|
add_settings_field(
|
|
'quiztech_smtp_host',
|
|
__( 'SMTP Host', 'quiztech' ),
|
|
[ $this, 'render_text_field' ],
|
|
$this->page_slug,
|
|
'quiztech_smtp_section',
|
|
[
|
|
'id' => 'quiztech_smtp_host',
|
|
'option_name' => $this->option_name,
|
|
'key' => 'smtp_host',
|
|
'description' => __( 'e.g., smtp.example.com', 'quiztech' )
|
|
]
|
|
);
|
|
|
|
// SMTP Port Field
|
|
add_settings_field(
|
|
'quiztech_smtp_port',
|
|
__( 'SMTP Port', 'quiztech' ),
|
|
[ $this, 'render_text_field' ], // Use text field, sanitize as number later
|
|
$this->page_slug,
|
|
'quiztech_smtp_section',
|
|
[
|
|
'id' => 'quiztech_smtp_port',
|
|
'option_name' => $this->option_name,
|
|
'key' => 'smtp_port',
|
|
'type' => 'number',
|
|
'description' => __( 'e.g., 587 (TLS) or 465 (SSL)', 'quiztech' )
|
|
]
|
|
);
|
|
|
|
// SMTP Encryption Field (Select)
|
|
add_settings_field(
|
|
'quiztech_smtp_encryption',
|
|
__( 'Encryption', 'quiztech' ),
|
|
[ $this, 'render_select_field' ], // New callback needed
|
|
$this->page_slug,
|
|
'quiztech_smtp_section',
|
|
[
|
|
'id' => 'quiztech_smtp_encryption',
|
|
'option_name' => $this->option_name,
|
|
'key' => 'smtp_encryption',
|
|
'options' => [
|
|
'' => __( 'None', 'quiztech' ),
|
|
'ssl' => __( 'SSL', 'quiztech' ),
|
|
'tls' => __( 'TLS', 'quiztech' ),
|
|
],
|
|
'description' => __( 'Select the encryption method.', 'quiztech' )
|
|
]
|
|
);
|
|
|
|
// SMTP Auth Field (Checkbox)
|
|
add_settings_field(
|
|
'quiztech_smtp_auth',
|
|
__( 'Use Authentication', 'quiztech' ),
|
|
[ $this, 'render_checkbox_field' ], // Reuse callback
|
|
$this->page_slug,
|
|
'quiztech_smtp_section',
|
|
[
|
|
'id' => 'quiztech_smtp_auth',
|
|
'option_name' => $this->option_name,
|
|
'key' => 'smtp_auth',
|
|
'description' => __( 'Enable if your SMTP server requires a username and password.', 'quiztech' )
|
|
]
|
|
);
|
|
|
|
// SMTP Username Field
|
|
add_settings_field(
|
|
'quiztech_smtp_username',
|
|
__( 'SMTP Username', 'quiztech' ),
|
|
[ $this, 'render_text_field' ],
|
|
$this->page_slug,
|
|
'quiztech_smtp_section',
|
|
[
|
|
'id' => 'quiztech_smtp_username',
|
|
'option_name' => $this->option_name,
|
|
'key' => 'smtp_username',
|
|
'description' => __( 'The username for SMTP authentication.', 'quiztech' )
|
|
]
|
|
);
|
|
|
|
// SMTP Password Field
|
|
add_settings_field(
|
|
'quiztech_smtp_password',
|
|
__( 'SMTP Password', 'quiztech' ),
|
|
[ $this, 'render_text_field' ],
|
|
$this->page_slug,
|
|
'quiztech_smtp_section',
|
|
[
|
|
'id' => 'quiztech_smtp_password',
|
|
'option_name' => $this->option_name,
|
|
'key' => 'smtp_password',
|
|
'type' => 'password',
|
|
'description' => __( 'The password for SMTP authentication. Stored as plain text in the database.', 'quiztech' )
|
|
]
|
|
);
|
|
|
|
// SMTP From Address Field
|
|
add_settings_field(
|
|
'quiztech_smtp_from_address',
|
|
__( 'From Email Address', 'quiztech' ),
|
|
[ $this, 'render_text_field' ],
|
|
$this->page_slug,
|
|
'quiztech_smtp_section',
|
|
[
|
|
'id' => 'quiztech_smtp_from_address',
|
|
'option_name' => $this->option_name,
|
|
'key' => 'smtp_from_address',
|
|
'type' => 'email',
|
|
'description' => __( 'The email address emails will be sent from.', 'quiztech' )
|
|
]
|
|
);
|
|
|
|
// SMTP From Name Field
|
|
add_settings_field(
|
|
'quiztech_smtp_from_name',
|
|
__( 'From Name', 'quiztech' ),
|
|
[ $this, 'render_text_field' ],
|
|
$this->page_slug,
|
|
'quiztech_smtp_section',
|
|
[
|
|
'id' => 'quiztech_smtp_from_name',
|
|
'option_name' => $this->option_name,
|
|
'key' => 'smtp_from_name',
|
|
'description' => __( 'The name emails will be sent from.', 'quiztech' )
|
|
]
|
|
);
|
|
|
|
// Future settings sections/fields (e.g., email, defaults) should be registered here.
|
|
} // End register_settings()
|
|
|
|
/**
|
|
* Renders the main settings page container and form.
|
|
*/
|
|
public function render_settings_page() {
|
|
?>
|
|
<div class="wrap">
|
|
<h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
|
|
<form action="options.php" method="post">
|
|
<?php
|
|
// Output security fields for the registered setting group
|
|
settings_fields( $this->option_group );
|
|
|
|
// Output setting sections and their fields
|
|
do_settings_sections( $this->page_slug );
|
|
|
|
// Output save settings button
|
|
submit_button( __( 'Save Settings', 'quiztech' ) );
|
|
?>
|
|
|
|
<hr />
|
|
<h2><?php esc_html_e( 'Test SMTP Settings', 'quiztech' ); ?></h2>
|
|
<p><?php esc_html_e( 'Click the button below to send a test email to the site administrator', 'quiztech' ); ?> (<?php echo esc_html( get_option('admin_email') ); ?>) <?php esc_html_e( 'using the currently saved settings.', 'quiztech' ); ?></p>
|
|
<button type="button" id="quiztech-test-email-button" class="button">
|
|
<?php esc_html_e( 'Send Test Email', 'quiztech' ); ?>
|
|
</button>
|
|
<span id="quiztech-test-email-status" style="margin-left: 10px;"></span>
|
|
|
|
<script type="text/javascript">
|
|
jQuery(document).ready(function($) {
|
|
$('#quiztech-test-email-button').on('click', function() {
|
|
var button = $(this);
|
|
var statusSpan = $('#quiztech-test-email-status');
|
|
|
|
statusSpan.text('<?php echo esc_js( __( 'Sending...', 'quiztech' ) ); ?>').css('color', '');
|
|
button.prop('disabled', true);
|
|
|
|
$.post(ajaxurl, {
|
|
action: 'quiztech_send_test_email',
|
|
_ajax_nonce: '<?php echo wp_create_nonce( 'quiztech_test_email_nonce' ); ?>'
|
|
}, function(response) {
|
|
if (response.success) {
|
|
statusSpan.text('<?php echo esc_js( __( 'Test email sent successfully!', 'quiztech' ) ); ?>').css('color', 'green');
|
|
} else {
|
|
var errorMsg = response.data && response.data.message ? response.data.message : '<?php echo esc_js( __( 'An unknown error occurred.', 'quiztech' ) ); ?>';
|
|
statusSpan.text('<?php echo esc_js( __( 'Error:', 'quiztech' ) ); ?> ' + errorMsg).css('color', 'red');
|
|
}
|
|
button.prop('disabled', false);
|
|
}).fail(function() {
|
|
statusSpan.text('<?php echo esc_js( __( 'AJAX request failed.', 'quiztech' ) ); ?>').css('color', 'red');
|
|
button.prop('disabled', false);
|
|
});
|
|
});
|
|
});
|
|
</script>
|
|
</form>
|
|
</div>
|
|
<?php
|
|
}
|
|
|
|
/**
|
|
* Renders a standard text input field for a setting.
|
|
* Expects args: 'id', 'option_name', 'key', 'description' (optional), 'type' (optional, default 'text')
|
|
*
|
|
* @param array $args Arguments passed from add_settings_field.
|
|
*/
|
|
public function render_text_field( $args ) {
|
|
$options = get_option( $args['option_name'], [] ); // Get all settings or default to empty array
|
|
$value = isset( $options[ $args['key'] ] ) ? $options[ $args['key'] ] : '';
|
|
$type = isset( $args['type'] ) ? $args['type'] : 'text';
|
|
?>
|
|
<input
|
|
type="<?php echo esc_attr( $type ); ?>"
|
|
id="<?php echo esc_attr( $args['id'] ); ?>"
|
|
name="<?php echo esc_attr( $args['option_name'] . '[' . $args['key'] . ']' ); ?>"
|
|
value="<?php echo esc_attr( $value ); ?>"
|
|
class="regular-text"
|
|
/>
|
|
<?php if ( isset( $args['description'] ) ) : ?>
|
|
<p class="description"><?php echo esc_html( $args['description'] ); ?></p>
|
|
<?php endif; ?>
|
|
<?php
|
|
}
|
|
|
|
|
|
/**
|
|
* Renders the description for the SMTP settings section.
|
|
*/
|
|
public function render_smtp_section_description() {
|
|
echo '<p>' . esc_html__( 'Configure your SMTP server details for reliable email sending. If disabled, WordPress will use the default PHP mail function.', 'quiztech' ) . '</p>';
|
|
}
|
|
|
|
/**
|
|
* Renders a checkbox input field for a setting.
|
|
* Expects args: 'id', 'option_name', 'key', 'description' (optional)
|
|
*
|
|
* @param array $args Arguments passed from add_settings_field.
|
|
*/
|
|
public function render_checkbox_field( $args ) {
|
|
$options = get_option( $args['option_name'], [] );
|
|
$checked = isset( $options[ $args['key'] ] ) && $options[ $args['key'] ] ? 'checked' : '';
|
|
?>
|
|
<input
|
|
type="checkbox"
|
|
id="<?php echo esc_attr( $args['id'] ); ?>"
|
|
name="<?php echo esc_attr( $args['option_name'] . '[' . $args['key'] . ']' ); ?>"
|
|
value="1" <?php // Value is 1 when checked ?>
|
|
<?php echo esc_attr( $checked ); ?>
|
|
/>
|
|
<?php if ( isset( $args['description'] ) ) : ?>
|
|
<label for="<?php echo esc_attr( $args['id'] ); ?>"> <?php echo esc_html( $args['description'] ); ?></label>
|
|
<?php endif; ?>
|
|
<?php
|
|
}
|
|
|
|
/**
|
|
* Renders a select dropdown field for a setting.
|
|
* Expects args: 'id', 'option_name', 'key', 'options' (array of value => label), 'description' (optional)
|
|
*
|
|
* @param array $args Arguments passed from add_settings_field.
|
|
*/
|
|
public function render_select_field( $args ) {
|
|
$options = get_option( $args['option_name'], [] );
|
|
$value = isset( $options[ $args['key'] ] ) ? $options[ $args['key'] ] : '';
|
|
?>
|
|
<select
|
|
id="<?php echo esc_attr( $args['id'] ); ?>"
|
|
name="<?php echo esc_attr( $args['option_name'] . '[' . $args['key'] . ']' ); ?>"
|
|
>
|
|
<?php foreach ( $args['options'] as $option_value => $option_label ) : ?>
|
|
<option value="<?php echo esc_attr( $option_value ); ?>" <?php selected( $value, $option_value ); ?>>
|
|
<?php echo esc_html( $option_label ); ?>
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
<?php if ( isset( $args['description'] ) ) : ?>
|
|
<p class="description"><?php echo esc_html( $args['description'] ); ?></p>
|
|
<?php endif; ?>
|
|
<?php
|
|
}
|
|
|
|
/**
|
|
* Sanitizes the settings array before saving.
|
|
*
|
|
* @param array $input The raw input array from the form.
|
|
* @return array The sanitized array.
|
|
*/
|
|
public function sanitize_settings( $input ) {
|
|
$sanitized_input = [];
|
|
|
|
if ( isset( $input['stripe_public_key'] ) ) {
|
|
// Basic sanitization, might need stricter validation (e.g., regex for pk_live_/pk_test_)
|
|
$sanitized_input['stripe_public_key'] = sanitize_text_field( $input['stripe_public_key'] );
|
|
}
|
|
if ( isset( $input['stripe_secret_key'] ) ) {
|
|
// Basic sanitization, might need stricter validation (e.g., regex for sk_live_/sk_test_)
|
|
$sanitized_input['stripe_secret_key'] = sanitize_text_field( $input['stripe_secret_key'] );
|
|
|
|
// Sanitize SMTP settings
|
|
$smtp_fields = [
|
|
'smtp_host' => 'sanitize_text_field',
|
|
'smtp_port' => 'absint', // Sanitize as integer
|
|
'smtp_encryption' => 'sanitize_key', // 'ssl', 'tls', or ''
|
|
'smtp_username' => 'sanitize_text_field',
|
|
'smtp_password' => 'sanitize_text_field', // Keep as text, WP handles display
|
|
'smtp_from_address' => 'sanitize_email',
|
|
'smtp_from_name' => 'sanitize_text_field',
|
|
];
|
|
|
|
foreach ( $smtp_fields as $key => $sanitize_callback ) {
|
|
if ( isset( $input[ $key ] ) ) {
|
|
$sanitized_input[ $key ] = call_user_func( $sanitize_callback, $input[ $key ] );
|
|
}
|
|
}
|
|
|
|
// Checkboxes (only save if present and value is '1')
|
|
$checkbox_fields = [ 'smtp_enabled', 'smtp_auth' ];
|
|
foreach ( $checkbox_fields as $key ) {
|
|
$sanitized_input[ $key ] = ( isset( $input[ $key ] ) && $input[ $key ] === '1' ) ? 1 : 0;
|
|
}
|
|
|
|
// Validate encryption value
|
|
if ( ! in_array( $sanitized_input['smtp_encryption'], [ '', 'ssl', 'tls' ], true ) ) {
|
|
$sanitized_input['smtp_encryption'] = ''; // Default to none if invalid
|
|
}
|
|
|
|
// Future settings added should have their sanitization logic implemented here.
|
|
|
|
return $sanitized_input;
|
|
}
|
|
|
|
|
|
/**
|
|
* Handles the AJAX request to send a test email.
|
|
*/
|
|
public function handle_send_test_email_ajax() {
|
|
check_ajax_referer( 'quiztech_test_email_nonce', '_ajax_nonce' );
|
|
|
|
if ( ! current_user_can( 'manage_options' ) ) {
|
|
wp_send_json_error( [ 'message' => __( 'Permission denied.', 'quiztech' ) ], 403 );
|
|
}
|
|
|
|
$admin_email = get_option( 'admin_email' );
|
|
if ( ! is_email( $admin_email ) ) {
|
|
wp_send_json_error( [ 'message' => __( 'Invalid site administrator email address.', 'quiztech' ) ] );
|
|
}
|
|
|
|
$subject = __( 'Quiztech SMTP Test Email', 'quiztech' );
|
|
$message = __( 'This is a test email sent from the Quiztech plugin settings page to verify your SMTP configuration.', 'quiztech' );
|
|
$headers = []; // Can add headers if needed, e.g., Content-Type
|
|
|
|
// Temporarily hook into phpmailer to capture errors
|
|
$error_message = '';
|
|
add_action( 'wp_mail_failed', function ( $wp_error ) use ( &$error_message ) {
|
|
if ( is_wp_error( $wp_error ) ) {
|
|
$error_message = $wp_error->get_error_message();
|
|
}
|
|
}, 10, 1 );
|
|
|
|
$sent = wp_mail( $admin_email, $subject, $message, $headers );
|
|
|
|
// Remove the temporary hook
|
|
// Note: Removing anonymous functions requires more complex handling (e.g., storing the closure in a property).
|
|
// For simplicity in this test function, we'll leave it, but be aware it persists for the request.
|
|
// A better approach for production code might involve a dedicated class or named function.
|
|
// remove_action( 'wp_mail_failed', $this->capture_wp_mail_error_closure ); // Example if stored
|
|
|
|
if ( $sent ) {
|
|
wp_send_json_success();
|
|
} else {
|
|
$error_to_send = ! empty( $error_message ) ? $error_message : __( 'The email could not be sent. Check your SMTP settings and server logs.', 'quiztech' );
|
|
wp_send_json_error( [ 'message' => $error_to_send ] );
|
|
}
|
|
}
|
|
}
|