v2.0 重构

This commit is contained in:
文派备案 2025-05-20 22:52:24 +08:00
parent f7fe8d63e0
commit 31bf7145ea
14 changed files with 6815 additions and 1103 deletions

514
admin/domains-page.php Normal file
View file

@ -0,0 +1,514 @@
<?php
/**
* Domains administration page
*
* @package WP Domain Mapping
*/
// Prevent direct access
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
?>
<div class="wrap">
<h1><?php echo esc_html( get_admin_page_title() ); ?>
<span style="font-size: 13px; padding-left: 10px;">
<?php printf( esc_html__( 'Version: %s', 'wp-domain-mapping' ), esc_html( WP_DOMAIN_MAPPING_VERSION ) ); ?>
</span>
<a href="https://wpmultisite.com/document/wp-domain-mapping" target="_blank" class="button button-secondary" style="margin-left: 10px;">
<?php esc_html_e( 'Documentation', 'wp-domain-mapping' ); ?>
</a>
<a href="https://wpmultisite.com/forums/" target="_blank" class="button button-secondary">
<?php esc_html_e( 'Support', 'wp-domain-mapping' ); ?>
</a>
</h1>
<div class="card domain-mapping-card">
<h2><?php echo $edit_row ? esc_html__( 'Edit Domain', 'wp-domain-mapping' ) : esc_html__( 'Add New Domain', 'wp-domain-mapping' ); ?></h2>
<div id="edit-domain-status" class="notice" style="display:none;"></div>
<?php dm_edit_domain( $edit_row ); ?>
</div>
<div class="card domain-mapping-card">
<h2><?php esc_html_e( 'Search & Filter Domains', 'wp-domain-mapping' ); ?></h2>
<form method="GET" id="domain-filter-form">
<input type="hidden" name="page" value="domains" />
<div class="search-form">
<div class="search-form-field">
<label for="domain"><?php esc_html_e( 'Domain:', 'wp-domain-mapping' ); ?></label>
<input type="text" id="domain" name="s" value="<?php echo esc_attr( isset( $_GET['s'] ) ? $_GET['s'] : '' ); ?>" class="regular-text" placeholder="example.com" />
</div>
<div class="search-form-field">
<label for="blog_id"><?php esc_html_e( 'Site ID:', 'wp-domain-mapping' ); ?></label>
<input type="number" id="blog_id" name="blog_id" value="<?php echo esc_attr( isset( $_GET['blog_id'] ) ? $_GET['blog_id'] : '' ); ?>" class="small-text" min="1" />
</div>
<div class="search-form-field">
<label for="active"><?php esc_html_e( 'Primary:', 'wp-domain-mapping' ); ?></label>
<select id="active" name="active">
<option value=""><?php esc_html_e( 'All', 'wp-domain-mapping' ); ?></option>
<option value="1" <?php selected( isset( $_GET['active'] ) && $_GET['active'] == '1' ); ?>>
<?php esc_html_e( 'Yes', 'wp-domain-mapping' ); ?>
</option>
<option value="0" <?php selected( isset( $_GET['active'] ) && $_GET['active'] == '0' ); ?>>
<?php esc_html_e( 'No', 'wp-domain-mapping' ); ?>
</option>
</select>
</div>
<div class="search-form-submit">
<input type="submit" class="button button-secondary" value="<?php esc_attr_e( 'Filter', 'wp-domain-mapping' ); ?>" />
<?php if ( isset( $_GET['s'] ) || isset( $_GET['blog_id'] ) || isset( $_GET['active'] ) ) : ?>
<a href="<?php echo esc_url( admin_url( 'network/sites.php?page=domains' ) ); ?>" class="button button-link">
<?php esc_html_e( 'Clear', 'wp-domain-mapping' ); ?>
</a>
<?php endif; ?>
</div>
</div>
</form>
</div>
<div class="card domain-mapping-card">
<div class="domain-mapping-tabs">
<button type="button" class="domain-mapping-tab active" data-tab="manage-domains">
<?php esc_html_e( 'Manage Domains', 'wp-domain-mapping' ); ?>
</button>
<button type="button" class="domain-mapping-tab" data-tab="domain-logs">
<?php esc_html_e( 'Domain Logs', 'wp-domain-mapping' ); ?>
</button>
</div>
<div class="domain-mapping-content">
<div class="domain-mapping-section" data-section="manage-domains">
<div id="domain-status" class="notice" style="display:none;"></div>
<form id="domain-list-form" method="POST">
<?php
$per_page = isset( $_GET['per_page'] ) ? absint( $_GET['per_page'] ) : 20;
$paged = isset( $_GET['paged'] ) ? absint( $_GET['paged'] ) : 1;
$offset = ( $paged - 1 ) * $per_page;
// Build the WHERE clause for filtering
$where = array();
if ( ! empty( $_GET['s'] ) ) {
$where[] = $wpdb->prepare(
"domain LIKE %s",
'%' . $wpdb->esc_like( sanitize_text_field( $_GET['s'] ) ) . '%'
);
}
if ( ! empty( $_GET['blog_id'] ) ) {
$where[] = $wpdb->prepare(
"blog_id = %d",
absint( $_GET['blog_id'] )
);
}
if ( isset( $_GET['active'] ) && $_GET['active'] !== '' ) {
$where[] = $wpdb->prepare(
"active = %d",
absint( $_GET['active'] )
);
}
$where_sql = $where ? ' WHERE ' . implode( ' AND ', $where ) : '';
// Count total items for pagination
$total_items = $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->base_prefix}" . WP_DOMAIN_MAPPING_TABLE_DOMAINS . $where_sql );
$total_pages = ceil( $total_items / $per_page );
// Get the domains with pagination
$rows = $wpdb->get_results( $wpdb->prepare(
"SELECT * FROM {$wpdb->base_prefix}" . WP_DOMAIN_MAPPING_TABLE_DOMAINS . $where_sql . " ORDER BY id DESC LIMIT %d, %d",
$offset,
$per_page
));
// Display the domains table
dm_domain_listing( $rows );
// Pagination
if ( $total_pages > 1 ) :
?>
<div class="tablenav bottom">
<div class="tablenav-pages">
<?php
echo paginate_links( array(
'base' => add_query_arg( 'paged', '%#%' ),
'format' => '',
'prev_text' => __( '&laquo;' ),
'next_text' => __( '&raquo;' ),
'total' => $total_pages,
'current' => $paged,
'mid_size' => 2,
'end_size' => 1,
) );
?>
<span class="displaying-num">
<?php
printf(
/* translators: %s: number of items */
_n( '%s item', '%s items', $total_items, 'wp-domain-mapping' ),
number_format_i18n( $total_items )
);
?>
</span>
</div>
</div>
<?php endif; ?>
<p class="description">
<?php
printf(
/* translators: %s: IDN warning message */
__( '<strong>Note:</strong> %s', 'wp-domain-mapping' ),
dm_idn_warning()
);
?>
</p>
</form>
</div>
<div class="domain-mapping-section" data-section="domain-logs" style="display:none;">
<?php dm_domain_logs(); ?>
</div>
</div>
</div>
<div class="card domain-mapping-card">
<h2><?php esc_html_e( 'Domain Statistics', 'wp-domain-mapping' ); ?></h2>
<table class="wp-list-table widefat fixed striped">
<tbody>
<tr>
<th><?php esc_html_e( 'Total Domains', 'wp-domain-mapping' ); ?></th>
<td><?php echo esc_html( $total_domains ); ?></td>
</tr>
<tr>
<th><?php esc_html_e( 'Primary Domains', 'wp-domain-mapping' ); ?></th>
<td><?php echo esc_html( $primary_domains ); ?></td>
</tr>
<tr>
<th><?php esc_html_e( 'Sites with Mapped Domains', 'wp-domain-mapping' ); ?></th>
<td>
<?php
$sites_with_domains = $wpdb->get_var( "SELECT COUNT(DISTINCT blog_id) FROM {$wpdb->base_prefix}" . WP_DOMAIN_MAPPING_TABLE_DOMAINS );
echo esc_html( $sites_with_domains );
?>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<script>
jQuery(document).ready(function($) {
// Tab switching functionality
$('.domain-mapping-tab').on('click', function() {
$('.domain-mapping-tab').removeClass('active');
$(this).addClass('active');
var tab = $(this).data('tab');
$('.domain-mapping-section').hide();
$('.domain-mapping-section[data-section="' + tab + '"]').show();
});
// Helper function for showing notices
function showNotice(selector, message, type) {
$(selector)
.removeClass('notice-success notice-error notice-warning notice-info')
.addClass('notice-' + type)
.html('<p>' + message + '</p>')
.show()
.delay(3000)
.fadeOut();
}
// Handle domain edit/add form submission
$('#edit-domain-form').on('submit', function(e) {
e.preventDefault();
// Validate form
var blogId = $('#blog_id').val();
var domain = $('#domain').val();
if (!blogId || !domain) {
showNotice('#edit-domain-status', '<?php esc_html_e( 'Please fill in all required fields.', 'wp-domain-mapping' ); ?>', 'error');
return;
}
var formData = $(this).serializeArray();
formData.push({name: 'action', value: 'dm_handle_actions'});
formData.push({name: 'action_type', value: 'save'});
formData.push({name: 'nonce', value: '<?php echo wp_create_nonce( 'domain_mapping' ); ?>'});
$('#edit-domain-status').html('<p><?php esc_html_e( 'Saving...', 'wp-domain-mapping' ); ?></p>').show();
$.ajax({
url: ajaxurl,
type: 'POST',
data: formData,
success: function(response) {
if (response.success) {
showNotice('#edit-domain-status', response.data, 'success');
setTimeout(function() {
location.href = '<?php echo esc_js( admin_url( 'network/sites.php?page=domains' ) ); ?>';
}, 1000);
} else {
showNotice('#edit-domain-status', response.data || '<?php esc_html_e( 'Failed to save domain.', 'wp-domain-mapping' ); ?>', 'error');
}
},
error: function() {
showNotice('#edit-domain-status', '<?php esc_html_e( 'Server error occurred.', 'wp-domain-mapping' ); ?>', 'error');
}
});
});
// Handle domain list bulk actions
$('#domain-list-form').on('submit', function(e) {
e.preventDefault();
var selectedDomains = [];
$('.domain-checkbox:checked').each(function() {
selectedDomains.push($(this).val());
});
if (selectedDomains.length === 0) {
showNotice('#domain-status', '<?php esc_html_e( 'Please select at least one domain.', 'wp-domain-mapping' ); ?>', 'error');
return;
}
var action = $('#bulk-action-selector-top').val();
if (action === '-1') return;
if (!confirm('<?php esc_html_e( 'Are you sure you want to delete the selected domains?', 'wp-domain-mapping' ); ?>')) {
return;
}
$('#domain-status').html('<p><?php esc_html_e( 'Processing...', 'wp-domain-mapping' ); ?></p>').show();
$.ajax({
url: ajaxurl,
type: 'POST',
data: {
action: 'dm_handle_actions',
action_type: 'delete',
domains: selectedDomains,
nonce: '<?php echo wp_create_nonce( 'domain_mapping' ); ?>'
},
success: function(response) {
if (response.success) {
showNotice('#domain-status', response.data, 'success');
setTimeout(function() {
location.reload();
}, 1000);
} else {
showNotice('#domain-status', response.data || '<?php esc_html_e( 'Failed to delete domains.', 'wp-domain-mapping' ); ?>', 'error');
}
},
error: function() {
showNotice('#domain-status', '<?php esc_html_e( 'Server error occurred.', 'wp-domain-mapping' ); ?>', 'error');
}
});
});
});
</script>
<style>
/* Main cards */
.domain-mapping-card {
background: #fff;
border: 1px solid #ccd0d4;
border-radius: 4px;
max-width: unset;
margin-top: 20px;
padding: 20px;
box-shadow: 0 1px 1px rgba(0,0,0,.04);
}
/* Tabs */
.domain-mapping-tabs {
display: flex;
flex-wrap: wrap;
gap: 5px;
border-bottom: 1px solid #c3c4c7;
margin-bottom: 20px;
}
.domain-mapping-tab {
padding: 8px 16px;
border: none;
background: none;
cursor: pointer;
font-size: 14px;
border-bottom: 2px solid transparent;
}
.domain-mapping-tab.active {
border-bottom: 2px solid #007cba;
font-weight: 600;
background: #f0f0f1;
}
.domain-mapping-tab:hover:not(.active) {
background: #f0f0f1;
border-bottom-color: #dcdcde;
}
.domain-mapping-content {
flex: 1;
}
/* Search form */
.search-form {
display: flex;
flex-wrap: wrap;
align-items: flex-end;
gap: 15px;
margin-bottom: 15px;
}
.search-form-field {
display: flex;
flex-direction: column;
min-width: 180px;
}
.search-form-field label {
margin-bottom: 5px;
font-weight: 500;
}
.search-form-submit {
display: flex;
align-items: center;
gap: 10px;
}
/* Tables */
.tablenav {
margin: 10px 0;
display: flex;
align-items: center;
}
.tablenav-pages {
margin-left: auto;
}
.tablenav-pages a,
.tablenav-pages span.current {
display: inline-block;
min-width: 17px;
padding: 3px 5px 7px;
background: #f0f0f1;
font-size: 16px;
line-height: 1;
font-weight: 400;
text-align: center;
text-decoration: none;
}
.tablenav-pages span.current {
background: #007cba;
color: #fff;
border-color: #007cba;
}
.displaying-num {
margin-left: 10px;
color: #555;
}
.domains-table th,
.logs-table th {
font-weight: 600;
}
.column-site-id {
width: 80px;
}
.column-site-name {
width: 20%;
}
.column-primary {
width: 80px;
text-align: center;
}
.column-actions {
width: 120px;
}
/* Form elements */
.form-table th {
width: 200px;
padding: 15px 10px 15px 0;
}
.form-table td {
padding: 15px 0;
}
.description {
color: #666;
font-size: 13px;
margin-top: 4px;
}
/* Notices */
.notice {
padding: 8px 12px;
border-radius: 3px;
margin: 5px 0 15px;
}
.notice p {
margin: 0.5em 0;
padding: 2px;
}
.notice-success {
background-color: #f0f9eb;
border-left: 4px solid #46b450;
}
.notice-error {
background-color: #fef0f0;
border-left: 4px solid #dc3232;
}
.notice-warning {
background-color: #fff8e5;
border-left: 4px solid #ffb900;
}
.notice-info {
background-color: #f0f6fa;
border-left: 4px solid #00a0d2;
}
/* Responsive */
@media screen and (max-width: 782px) {
.search-form {
flex-direction: column;
align-items: stretch;
}
.search-form-field {
min-width: 100%;
}
.form-table th {
width: 100%;
display: block;
}
.form-table td {
display: block;
padding: 0 0 15px;
}
}
</style>

288
admin/logs-table.php Normal file
View file

@ -0,0 +1,288 @@
<?php
/**
* Logs table display for domain mapping
*
* @package WP Domain Mapping
*/
// Prevent direct access
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
// Get pagination parameters
$per_page = isset( $_GET['logs_per_page'] ) ? absint( $_GET['logs_per_page'] ) : 50;
$paged = isset( $_GET['logs_paged'] ) ? absint( $_GET['logs_paged'] ) : 1;
$offset = ( $paged - 1 ) * $per_page;
// Get action filter
$action_filter = isset( $_GET['log_action'] ) ? sanitize_text_field( $_GET['log_action'] ) : '';
// Build WHERE clause for filtering
$where = array();
if ( ! empty( $action_filter ) ) {
$where[] = $wpdb->prepare( "action = %s", $action_filter );
}
$where_sql = $where ? ' WHERE ' . implode( ' AND ', $where ) : '';
// Count total logs for pagination
$total_logs = $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->base_prefix}" . WP_DOMAIN_MAPPING_TABLE_LOGS . $where_sql );
$total_pages = ceil( $total_logs / $per_page );
// Get logs with pagination
$logs = $wpdb->get_results( $wpdb->prepare(
"SELECT * FROM {$wpdb->base_prefix}" . WP_DOMAIN_MAPPING_TABLE_LOGS . $where_sql . " ORDER BY timestamp DESC LIMIT %d, %d",
$offset,
$per_page
));
// Get available actions for filter
$actions = $wpdb->get_col( "SELECT DISTINCT action FROM {$wpdb->base_prefix}" . WP_DOMAIN_MAPPING_TABLE_LOGS );
if ( ! $logs ) {
echo '<div class="notice notice-info"><p>' . esc_html__( 'No domain mapping logs available.', 'wp-domain-mapping' ) . '</p></div>';
return;
}
?>
<div class="tablenav top">
<form method="GET" id="logs-filter-form" class="logs-filter">
<input type="hidden" name="page" value="domains" />
<input type="hidden" name="tab" value="domain-logs" />
<div class="alignleft actions">
<label for="log_action" class="screen-reader-text"><?php esc_html_e( 'Filter by action', 'wp-domain-mapping' ); ?></label>
<select id="log_action" name="log_action">
<option value=""><?php esc_html_e( 'All actions', 'wp-domain-mapping' ); ?></option>
<?php foreach ( $actions as $action ) : ?>
<option value="<?php echo esc_attr( $action ); ?>" <?php selected( $action_filter, $action ); ?>>
<?php
switch ( $action ) {
case 'add':
esc_html_e( 'Added', 'wp-domain-mapping' );
break;
case 'edit':
esc_html_e( 'Updated', 'wp-domain-mapping' );
break;
case 'delete':
esc_html_e( 'Deleted', 'wp-domain-mapping' );
break;
default:
echo esc_html( ucfirst( $action ) );
}
?>
</option>
<?php endforeach; ?>
</select>
<input type="submit" class="button" value="<?php esc_attr_e( 'Filter', 'wp-domain-mapping' ); ?>" />
<?php if ( ! empty( $action_filter ) ) : ?>
<a href="<?php echo esc_url( add_query_arg( array( 'page' => 'domains', 'tab' => 'domain-logs' ), admin_url( 'network/sites.php' ) ) ); ?>" class="button">
<?php esc_html_e( 'Clear', 'wp-domain-mapping' ); ?>
</a>
<?php endif; ?>
</div>
</form>
<?php if ( $total_pages > 1 ) : ?>
<div class="tablenav-pages">
<?php
echo paginate_links( array(
'base' => add_query_arg( 'logs_paged', '%#%' ),
'format' => '',
'prev_text' => __( '&laquo;' ),
'next_text' => __( '&raquo;' ),
'total' => $total_pages,
'current' => $paged,
'mid_size' => 2,
'end_size' => 1,
) );
?>
<span class="displaying-num">
<?php
printf(
/* translators: %s: number of items */
_n( '%s log entry', '%s log entries', $total_logs, 'wp-domain-mapping' ),
number_format_i18n( $total_logs )
);
?>
</span>
</div>
<?php endif; ?>
</div>
<table class="wp-list-table widefat striped logs-table">
<thead>
<tr>
<th scope="col" class="column-user"><?php esc_html_e( 'User', 'wp-domain-mapping' ); ?></th>
<th scope="col" class="column-action"><?php esc_html_e( 'Action', 'wp-domain-mapping' ); ?></th>
<th scope="col" class="column-domain"><?php esc_html_e( 'Domain', 'wp-domain-mapping' ); ?></th>
<th scope="col" class="column-site"><?php esc_html_e( 'Site', 'wp-domain-mapping' ); ?></th>
<th scope="col" class="column-date"><?php esc_html_e( 'Date', 'wp-domain-mapping' ); ?></th>
</tr>
</thead>
<tbody>
<?php foreach ( $logs as $log ) :
// Get user data
$user_data = get_userdata( $log->user_id );
$username = $user_data
? sprintf(
'<a href="%s">%s</a>',
esc_url( network_admin_url( 'user-edit.php?user_id=' . $log->user_id ) ),
esc_html( $user_data->user_login )
)
: sprintf( esc_html__( 'User #%d', 'wp-domain-mapping' ), $log->user_id );
// Format action for display
switch ( $log->action ) {
case 'add':
$action_display = '<span class="log-action log-action-add">' . esc_html__( 'Added', 'wp-domain-mapping' ) . '</span>';
break;
case 'edit':
$action_display = '<span class="log-action log-action-edit">' . esc_html__( 'Updated', 'wp-domain-mapping' ) . '</span>';
break;
case 'delete':
$action_display = '<span class="log-action log-action-delete">' . esc_html__( 'Deleted', 'wp-domain-mapping' ) . '</span>';
break;
default:
$action_display = '<span class="log-action">' . esc_html( ucfirst( $log->action ) ) . '</span>';
}
// Get site name
$site_name = get_blog_option( $log->blog_id, 'blogname', '' );
$site_link = ! empty( $site_name )
? sprintf(
'<a href="%s">%s</a>',
esc_url( network_admin_url( 'site-info.php?id=' . $log->blog_id ) ),
esc_html( $site_name )
)
: sprintf( esc_html__( 'Site #%d', 'wp-domain-mapping' ), $log->blog_id );
// Format timestamp for display
$timestamp = mysql2date( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), $log->timestamp );
$time_diff = human_time_diff( strtotime( $log->timestamp ), current_time( 'timestamp' ) );
?>
<tr>
<td class="column-user"><?php echo $username; ?></td>
<td class="column-action"><?php echo $action_display; ?></td>
<td class="column-domain">
<a href="<?php echo esc_url( dm_ensure_protocol( $log->domain ) ); ?>" target="_blank">
<?php echo esc_html( $log->domain ); ?>
<span class="dashicons dashicons-external" style="font-size: 14px; line-height: 1.3; opacity: 0.7;"></span>
</a>
</td>
<td class="column-site">
<?php echo $site_link; ?>
</td>
<td class="column-date">
<abbr title="<?php echo esc_attr( $timestamp ); ?>">
<?php
/* translators: %s: time ago */
printf( esc_html__( '%s ago', 'wp-domain-mapping' ), $time_diff );
?>
</abbr>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php if ( $total_pages > 1 ) : ?>
<div class="tablenav bottom">
<div class="tablenav-pages">
<?php
echo paginate_links( array(
'base' => add_query_arg( 'logs_paged', '%#%' ),
'format' => '',
'prev_text' => __( '&laquo;' ),
'next_text' => __( '&raquo;' ),
'total' => $total_pages,
'current' => $paged,
'mid_size' => 2,
'end_size' => 1,
) );
?>
<span class="displaying-num">
<?php
printf(
/* translators: %s: number of items */
_n( '%s log entry', '%s log entries', $total_logs, 'wp-domain-mapping' ),
number_format_i18n( $total_logs )
);
?>
</span>
</div>
</div>
<?php endif; ?>
<style>
/* Logs table styles */
.logs-filter {
display: flex;
align-items: center;
margin-bottom: 10px;
}
.logs-table .column-user,
.logs-table .column-site {
width: 15%;
}
.logs-table .column-action {
width: 10%;
}
.logs-table .column-date {
width: 15%;
}
.log-action {
display: inline-block;
padding: 2px 8px;
border-radius: 3px;
font-size: 12px;
font-weight: bold;
}
.log-action-add {
background-color: #dff0d8;
color: #3c763d;
}
.log-action-edit {
background-color: #d9edf7;
color: #31708f;
}
.log-action-delete {
background-color: #f2dede;
color: #a94442;
}
/* Pagination */
.tablenav-pages a,
.tablenav-pages span.current {
display: inline-block;
min-width: 17px;
padding: 3px 5px 7px;
background: #f0f0f1;
font-size: 16px;
line-height: 1;
font-weight: 400;
text-align: center;
text-decoration: none;
}
.tablenav-pages span.current {
background: #007cba;
color: #fff;
border-color: #007cba;
}
.displaying-num {
margin-left: 10px;
color: #555;
}
</style>

522
admin/settings-page.php Normal file
View file

@ -0,0 +1,522 @@
<?php
/**
* Settings administration page
*
* @package WP Domain Mapping
*/
// Prevent direct access
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
// Get current options
$dm_ipaddress = get_site_option( 'dm_ipaddress', '' );
$dm_cname = get_site_option( 'dm_cname', '' );
$dm_remote_login = get_site_option( 'dm_remote_login', 1 );
$dm_301_redirect = get_site_option( 'dm_301_redirect', 0 );
$dm_redirect_admin = get_site_option( 'dm_redirect_admin', 1 );
$dm_user_settings = get_site_option( 'dm_user_settings', 1 );
$dm_no_primary_domain = get_site_option( 'dm_no_primary_domain', 0 );
// Get server IP address if not set
if ( empty( $dm_ipaddress ) ) {
$server_ip = isset( $_SERVER['SERVER_ADDR'] ) ? $_SERVER['SERVER_ADDR'] : '';
if ( empty( $server_ip ) && function_exists( 'gethostbyname' ) ) {
$server_ip = gethostbyname( $_SERVER['SERVER_NAME'] );
}
if ( $server_ip && filter_var( $server_ip, FILTER_VALIDATE_IP ) ) {
$dm_ipaddress = $server_ip;
}
}
// Display settings errors
settings_errors( 'dm_settings' );
?>
<div class="wrap">
<h1><?php echo esc_html( get_admin_page_title() ); ?>
<span style="font-size: 13px; padding-left: 10px;">
<?php printf( esc_html__( 'Version: %s', 'wp-domain-mapping' ), esc_html( WP_DOMAIN_MAPPING_VERSION ) ); ?>
</span>
<a href="https://wpmultisite.com/document/wp-domain-mapping" target="_blank" class="button button-secondary" style="margin-left: 10px;">
<?php esc_html_e( 'Documentation', 'wp-domain-mapping' ); ?>
</a>
<a href="https://wpmultisite.com/forums/" target="_blank" class="button button-secondary">
<?php esc_html_e( 'Support', 'wp-domain-mapping' ); ?>
</a>
</h1>
<div class="card domain-mapping-card">
<form method="POST">
<input type="hidden" name="action" value="update" />
<?php wp_nonce_field( 'domain_mapping' ); ?>
<h2><?php esc_html_e( 'Server Configuration', 'wp-domain-mapping' ); ?></h2>
<p><?php esc_html_e( 'Configure the IP address or CNAME for domain mapping.', 'wp-domain-mapping' ); ?></p>
<table class="form-table" role="presentation">
<tr>
<th scope="row"><label for="ipaddress"><?php esc_html_e( 'Server IP Address:', 'wp-domain-mapping' ); ?></label></th>
<td>
<input type="text" id="ipaddress" name="ipaddress" value="<?php echo esc_attr( $dm_ipaddress ); ?>" class="regular-text" />
<p class="description">
<?php esc_html_e( 'Enter the IP address(es) users should point their DNS A records to. Use commas to separate multiple IPs.', 'wp-domain-mapping' ); ?>
</p>
<?php if ( ! empty( $server_ip ) && $server_ip != $dm_ipaddress ) : ?>
<p class="description">
<?php printf(
/* translators: %s: Server IP address */
esc_html__( 'Detected server IP: %s', 'wp-domain-mapping' ),
'<code>' . esc_html( $server_ip ) . '</code>'
); ?>
</p>
<?php endif; ?>
</td>
</tr>
<tr>
<th scope="row"><label for="cname"><?php esc_html_e( 'Server CNAME Domain:', 'wp-domain-mapping' ); ?></label></th>
<td>
<input type="text" id="cname" name="cname" value="<?php echo esc_attr( $dm_cname ); ?>" class="regular-text" placeholder="server.example.com" />
<p class="description">
<?php
printf(
/* translators: %s: IDN warning message */
esc_html__( 'Use a CNAME instead of an IP (overrides IP settings). %s', 'wp-domain-mapping' ),
dm_idn_warning()
);
?>
</p>
</td>
</tr>
</table>
<h3><?php esc_html_e( 'Domain Options', 'wp-domain-mapping' ); ?></h3>
<table class="form-table" role="presentation">
<tr>
<th scope="row"></th>
<td>
<fieldset>
<legend class="screen-reader-text"><?php esc_html_e( 'Domain Options', 'wp-domain-mapping' ); ?></legend>
<label for="dm_remote_login">
<input type="checkbox" name="dm_remote_login" id="dm_remote_login" value="1" <?php checked( $dm_remote_login, 1 ); ?> />
<?php esc_html_e( 'Enable Remote Login', 'wp-domain-mapping' ); ?>
</label>
<p class="description">
<?php esc_html_e( 'Allows users to log in from mapped domains and be redirected to the original domain for authentication.', 'wp-domain-mapping' ); ?>
</p>
</fieldset>
</td>
</tr>
<tr>
<th scope="row"></th>
<td>
<fieldset>
<legend class="screen-reader-text"><?php esc_html_e( 'Permanent Redirect', 'wp-domain-mapping' ); ?></legend>
<label for="permanent_redirect">
<input type="checkbox" name="permanent_redirect" id="permanent_redirect" value="1" <?php checked( $dm_301_redirect, 1 ); ?> />
<?php esc_html_e( 'Use Permanent Redirect (301)', 'wp-domain-mapping' ); ?>
</label>
<p class="description">
<?php esc_html_e( 'Use 301 redirects instead of 302 redirects. This is better for SEO but may cause caching issues.', 'wp-domain-mapping' ); ?>
</p>
</fieldset>
</td>
</tr>
<tr>
<th scope="row"></th>
<td>
<fieldset>
<legend class="screen-reader-text"><?php esc_html_e( 'User Settings', 'wp-domain-mapping' ); ?></legend>
<label for="dm_user_settings">
<input type="checkbox" name="dm_user_settings" id="dm_user_settings" value="1" <?php checked( $dm_user_settings, 1 ); ?> />
<?php esc_html_e( 'Enable User Domain Mapping Page', 'wp-domain-mapping' ); ?>
</label>
<p class="description">
<?php esc_html_e( 'Allow site administrators to manage their domain mappings from the Tools menu.', 'wp-domain-mapping' ); ?>
</p>
</fieldset>
</td>
</tr>
<tr>
<th scope="row"></th>
<td>
<fieldset>
<legend class="screen-reader-text"><?php esc_html_e( 'Redirect Admin', 'wp-domain-mapping' ); ?></legend>
<label for="always_redirect_admin">
<input type="checkbox" name="always_redirect_admin" id="always_redirect_admin" value="1" <?php checked( $dm_redirect_admin, 1 ); ?> />
<?php esc_html_e( 'Redirect Admin Pages to Original Domain', 'wp-domain-mapping' ); ?>
</label>
<p class="description">
<?php esc_html_e( 'Force admin pages to use the original WordPress domain instead of the mapped domain.', 'wp-domain-mapping' ); ?>
</p>
</fieldset>
</td>
</tr>
<tr>
<th scope="row"></th>
<td>
<fieldset>
<legend class="screen-reader-text"><?php esc_html_e( 'Disable Primary Domain', 'wp-domain-mapping' ); ?></legend>
<label for="dm_no_primary_domain">
<input type="checkbox" name="dm_no_primary_domain" id="dm_no_primary_domain" value="1" <?php checked( $dm_no_primary_domain, 1 ); ?> />
<?php esc_html_e( 'Disable Primary Domain Check', 'wp-domain-mapping' ); ?>
</label>
<p class="description">
<?php esc_html_e( 'Do not redirect to the primary domain, but allow access through any mapped domain.', 'wp-domain-mapping' ); ?>
</p>
</fieldset>
</td>
</tr>
</table>
<p class="submit">
<input type="submit" class="button button-primary" value="<?php esc_attr_e( 'Save Configuration', 'wp-domain-mapping' ); ?>" />
<a href="<?php echo esc_url( admin_url( 'network/sites.php?page=domains' ) ); ?>" class="button button-secondary">
<?php esc_html_e( 'Manage Domains', 'wp-domain-mapping' ); ?>
</a>
</p>
</form>
</div>
<div class="card domain-mapping-card">
<h2><?php esc_html_e( 'DNS Setup Instructions', 'wp-domain-mapping' ); ?></h2>
<div class="dns-instructions">
<?php if ( ! empty( $dm_cname ) ) : ?>
<h3><?php esc_html_e( 'CNAME Method (Recommended)', 'wp-domain-mapping' ); ?></h3>
<p>
<?php
printf(
/* translators: %s: CNAME value */
esc_html__( 'Tell your users to add a DNS "CNAME" record for their domain pointing to: %s', 'wp-domain-mapping' ),
'<code>' . esc_html( $dm_cname ) . '</code>'
);
?>
</p>
<div class="dns-example">
<h4><?php esc_html_e( 'Example DNS Record', 'wp-domain-mapping' ); ?></h4>
<table class="widefat striped">
<thead>
<tr>
<th><?php esc_html_e( 'Type', 'wp-domain-mapping' ); ?></th>
<th><?php esc_html_e( 'Name', 'wp-domain-mapping' ); ?></th>
<th><?php esc_html_e( 'Value', 'wp-domain-mapping' ); ?></th>
</tr>
</thead>
<tbody>
<tr>
<td><code>CNAME</code></td>
<td><code>@</code> <?php esc_html_e( '(or empty)', 'wp-domain-mapping' ); ?></td>
<td><code><?php echo esc_html( $dm_cname ); ?></code></td>
</tr>
</tbody>
</table>
</div>
<?php endif; ?>
<?php if ( ! empty( $dm_ipaddress ) ) : ?>
<h3><?php esc_html_e( 'A Record Method', 'wp-domain-mapping' ); ?></h3>
<p>
<?php
printf(
/* translators: %s: IP address(es) */
esc_html__( 'Tell your users to add a DNS "A" record for their domain pointing to: %s', 'wp-domain-mapping' ),
'<code>' . esc_html( $dm_ipaddress ) . '</code>'
);
?>
</p>
<div class="dns-example">
<h4><?php esc_html_e( 'Example DNS Record', 'wp-domain-mapping' ); ?></h4>
<table class="widefat striped">
<thead>
<tr>
<th><?php esc_html_e( 'Type', 'wp-domain-mapping' ); ?></th>
<th><?php esc_html_e( 'Name', 'wp-domain-mapping' ); ?></th>
<th><?php esc_html_e( 'Value', 'wp-domain-mapping' ); ?></th>
</tr>
</thead>
<tbody>
<?php
$ips = array_map( 'trim', explode( ',', $dm_ipaddress ) );
foreach ( $ips as $index => $ip ) :
?>
<tr>
<td><code>A</code></td>
<td><code>@</code> <?php esc_html_e( '(or empty)', 'wp-domain-mapping' ); ?></td>
<td><code><?php echo esc_html( $ip ); ?></code></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>
<?php if ( empty( $dm_ipaddress ) && empty( $dm_cname ) ) : ?>
<div class="notice notice-warning">
<p>
<?php esc_html_e( 'Please configure either a Server IP Address or CNAME to provide DNS setup instructions.', 'wp-domain-mapping' ); ?>
</p>
</div>
<?php endif; ?>
<h3><?php esc_html_e( 'Additional DNS Tips', 'wp-domain-mapping' ); ?></h3>
<ul class="dns-tips">
<li>
<?php esc_html_e( 'Most DNS changes take 24-48 hours to fully propagate worldwide.', 'wp-domain-mapping' ); ?>
</li>
<li>
<?php esc_html_e( 'For "www" subdomain, create a separate CNAME record with "www" as the name pointing to the same value.', 'wp-domain-mapping' ); ?>
</li>
<li>
<?php esc_html_e( 'If you\'re using Cloudflare or similar services, you may need to adjust proxy settings.', 'wp-domain-mapping' ); ?>
</li>
<li>
<?php esc_html_e( 'For SSL to work properly, make sure your web server is configured with the appropriate SSL certificates for mapped domains.', 'wp-domain-mapping' ); ?>
</li>
</ul>
</div>
</div>
<div class="card domain-mapping-card">
<h2><?php esc_html_e( 'Installation Check', 'wp-domain-mapping' ); ?></h2>
<table class="widefat striped">
<tbody>
<tr>
<th><?php esc_html_e( 'Status', 'wp-domain-mapping' ); ?></th>
<th><?php esc_html_e( 'Check', 'wp-domain-mapping' ); ?></th>
<th><?php esc_html_e( 'Value', 'wp-domain-mapping' ); ?></th>
</tr>
<tr>
<td>
<?php if ( file_exists( WP_CONTENT_DIR . '/sunrise.php' ) ) : ?>
<span class="dashicons dashicons-yes-alt" style="color: #46b450;"></span>
<?php else : ?>
<span class="dashicons dashicons-no-alt" style="color: #dc3232;"></span>
<?php endif; ?>
</td>
<td><?php esc_html_e( 'sunrise.php file', 'wp-domain-mapping' ); ?></td>
<td>
<?php if ( file_exists( WP_CONTENT_DIR . '/sunrise.php' ) ) : ?>
<?php esc_html_e( 'Found', 'wp-domain-mapping' ); ?>
<?php else : ?>
<?php
printf(
/* translators: %s: WordPress content directory */
esc_html__( 'Not found - copy sunrise.php to %s', 'wp-domain-mapping' ),
'<code>' . esc_html( WP_CONTENT_DIR ) . '</code>'
);
?>
<?php endif; ?>
</td>
</tr>
<tr>
<td>
<?php if ( defined( 'SUNRISE' ) ) : ?>
<span class="dashicons dashicons-yes-alt" style="color: #46b450;"></span>
<?php else : ?>
<span class="dashicons dashicons-no-alt" style="color: #dc3232;"></span>
<?php endif; ?>
</td>
<td><?php esc_html_e( 'SUNRISE constant', 'wp-domain-mapping' ); ?></td>
<td>
<?php if ( defined( 'SUNRISE' ) ) : ?>
<?php
printf(
/* translators: %s: SUNRISE constant value */
esc_html__( 'Defined as: %s', 'wp-domain-mapping' ),
'<code>' . esc_html( SUNRISE ) . '</code>'
);
?>
<?php else : ?>
<?php esc_html_e( 'Not defined - add to wp-config.php: ', 'wp-domain-mapping' ); ?>
<code>define( 'SUNRISE', 'on' );</code>
<?php endif; ?>
</td>
</tr>
<tr>
<td>
<?php if ( defined( 'SUNRISE_LOADED' ) ) : ?>
<span class="dashicons dashicons-yes-alt" style="color: #46b450;"></span>
<?php else : ?>
<span class="dashicons dashicons-no-alt" style="color: #dc3232;"></span>
<?php endif; ?>
</td>
<td><?php esc_html_e( 'SUNRISE_LOADED', 'wp-domain-mapping' ); ?></td>
<td>
<?php if ( defined( 'SUNRISE_LOADED' ) ) : ?>
<?php esc_html_e( 'Loaded successfully', 'wp-domain-mapping' ); ?>
<?php else : ?>
<?php
if ( defined( 'SUNRISE' ) ) {
esc_html_e( 'Not loaded - make sure SUNRISE is defined before the require_once() in wp-config.php', 'wp-domain-mapping' );
} else {
esc_html_e( 'Not loaded - SUNRISE constant not defined', 'wp-domain-mapping' );
}
?>
<?php endif; ?>
</td>
</tr>
<tr>
<td>
<?php if ( ! defined( 'COOKIE_DOMAIN' ) ) : ?>
<span class="dashicons dashicons-yes-alt" style="color: #46b450;"></span>
<?php else : ?>
<span class="dashicons dashicons-no-alt" style="color: #dc3232;"></span>
<?php endif; ?>
</td>
<td><?php esc_html_e( 'COOKIE_DOMAIN', 'wp-domain-mapping' ); ?></td>
<td>
<?php if ( ! defined( 'COOKIE_DOMAIN' ) ) : ?>
<?php esc_html_e( 'Not defined (correct)', 'wp-domain-mapping' ); ?>
<?php else : ?>
<?php
printf(
/* translators: %s: COOKIE_DOMAIN constant value */
esc_html__( 'Defined as: %s - remove this from wp-config.php', 'wp-domain-mapping' ),
'<code>' . esc_html( COOKIE_DOMAIN ) . '</code>'
);
?>
<?php endif; ?>
</td>
</tr>
<tr>
<td>
<?php
global $wpdb;
$tables_exist = true;
foreach ( array(
$wpdb->base_prefix . WP_DOMAIN_MAPPING_TABLE_DOMAINS,
$wpdb->base_prefix . WP_DOMAIN_MAPPING_TABLE_LOGINS,
$wpdb->base_prefix . WP_DOMAIN_MAPPING_TABLE_LOGS,
) as $table ) {
if ( $wpdb->get_var( "SHOW TABLES LIKE '$table'" ) != $table ) {
$tables_exist = false;
break;
}
}
?>
<?php if ( $tables_exist ) : ?>
<span class="dashicons dashicons-yes-alt" style="color: #46b450;"></span>
<?php else : ?>
<span class="dashicons dashicons-no-alt" style="color: #dc3232;"></span>
<?php endif; ?>
</td>
<td><?php esc_html_e( 'Database tables', 'wp-domain-mapping' ); ?></td>
<td>
<?php if ( $tables_exist ) : ?>
<?php esc_html_e( 'All tables exist', 'wp-domain-mapping' ); ?>
<?php else : ?>
<?php esc_html_e( 'Some tables are missing - deactivate and reactivate the plugin', 'wp-domain-mapping' ); ?>
<?php endif; ?>
</td>
</tr>
<tr>
<td>
<?php if ( is_multisite() ) : ?>
<span class="dashicons dashicons-yes-alt" style="color: #46b450;"></span>
<?php else : ?>
<span class="dashicons dashicons-no-alt" style="color: #dc3232;"></span>
<?php endif; ?>
</td>
<td><?php esc_html_e( 'Multisite', 'wp-domain-mapping' ); ?></td>
<td>
<?php if ( is_multisite() ) : ?>
<?php esc_html_e( 'Enabled', 'wp-domain-mapping' ); ?>
<?php else : ?>
<?php esc_html_e( 'Not enabled - this plugin requires WordPress Multisite', 'wp-domain-mapping' ); ?>
<?php endif; ?>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<style>
/* Main cards */
.domain-mapping-card {
background: #fff;
border: 1px solid #ccd0d4;
border-radius: 4px;
max-width: unset;
margin-top: 20px;
padding: 20px;
box-shadow: 0 1px 1px rgba(0,0,0,.04);
}
/* Form elements */
.form-table th {
width: 200px;
padding: 15px 10px 15px 0;
}
.form-table td {
padding: 15px 0;
}
/* Description text */
.description {
color: #666;
font-size: 13px;
margin-top: 4px;
}
/* DNS instructions */
.dns-instructions {
margin-top: 10px;
}
.dns-example {
background: #f9f9f9;
border: 1px solid #e5e5e5;
border-radius: 3px;
padding: 15px;
margin: 15px 0;
}
.dns-example h4 {
margin-top: 0;
}
.dns-tips {
list-style: disc;
margin-left: 20px;
}
.dns-tips li {
margin-bottom: 8px;
}
/* Status indicators */
.dashicons-yes-alt,
.dashicons-no-alt {
font-size: 24px;
width: 24px;
height: 24px;
}
/* Notices */
.notice {
padding: 8px 12px;
border-radius: 3px;
margin: 5px 0 15px;
}
.notice p {
margin: 0.5em 0;
padding: 2px;
}
/* Responsive */
@media screen and (max-width: 782px) {
.form-table th {
width: 100%;
display: block;
}
.form-table td {
display: block;
padding: 0 0 15px;
}
}
</style>

964
admin/templates.php Normal file
View file

@ -0,0 +1,964 @@
<?php
// Prevent direct access
if (!defined('ABSPATH')) {
exit;
}
/**
* Render admin settings page (continued)
*/
function dm_render_settings_page_continued($dm_301_redirect, $dm_redirect_admin, $dm_user_settings, $dm_no_primary_domain, $dm_ipaddress, $dm_cname, $core) {
?>
<legend class="screen-reader-text"><?php _e('Permanent Redirect', 'wp-domain-mapping'); ?></legend>
<label for="permanent_redirect">
<input type="checkbox" name="permanent_redirect" id="permanent_redirect" value="1" <?php checked($dm_301_redirect, 1); ?> />
<?php _e('Use Permanent Redirect (301)', 'wp-domain-mapping'); ?>
</label>
<p class="description">
<?php _e('Use 301 redirects instead of 302 redirects. This is better for SEO but may cause caching issues.', 'wp-domain-mapping'); ?>
</p>
</fieldset>
</td>
</tr>
<tr>
<th scope="row"></th>
<td>
<fieldset>
<legend class="screen-reader-text"><?php _e('User Settings', 'wp-domain-mapping'); ?></legend>
<label for="dm_user_settings">
<input type="checkbox" name="dm_user_settings" id="dm_user_settings" value="1" <?php checked($dm_user_settings, 1); ?> />
<?php _e('Enable User Domain Mapping Page', 'wp-domain-mapping'); ?>
</label>
<p class="description">
<?php _e('Allow site administrators to manage their domain mappings from the Tools menu.', 'wp-domain-mapping'); ?>
</p>
</fieldset>
</td>
</tr>
<tr>
<th scope="row"></th>
<td>
<fieldset>
<legend class="screen-reader-text"><?php _e('Redirect Admin', 'wp-domain-mapping'); ?></legend>
<label for="always_redirect_admin">
<input type="checkbox" name="always_redirect_admin" id="always_redirect_admin" value="1" <?php checked($dm_redirect_admin, 1); ?> />
<?php _e('Redirect Admin Pages to Original Domain', 'wp-domain-mapping'); ?>
</label>
<p class="description">
<?php _e('Force admin pages to use the original WordPress domain instead of the mapped domain.', 'wp-domain-mapping'); ?>
</p>
</fieldset>
</td>
</tr>
<tr>
<th scope="row"></th>
<td>
<fieldset>
<legend class="screen-reader-text"><?php _e('Disable Primary Domain', 'wp-domain-mapping'); ?></legend>
<label for="dm_no_primary_domain">
<input type="checkbox" name="dm_no_primary_domain" id="dm_no_primary_domain" value="1" <?php checked($dm_no_primary_domain, 1); ?> />
<?php _e('Disable Primary Domain Check', 'wp-domain-mapping'); ?>
</label>
<p class="description">
<?php _e('Do not redirect to the primary domain, but allow access through any mapped domain.', 'wp-domain-mapping'); ?>
</p>
</fieldset>
</td>
</tr>
</table>
<p class="submit">
<input type="submit" class="button button-primary" value="<?php esc_attr_e('Save Configuration', 'wp-domain-mapping'); ?>" />
<a href="<?php echo esc_url(admin_url('network/sites.php?page=domains')); ?>" class="button button-secondary">
<?php _e('Manage Domains', 'wp-domain-mapping'); ?>
</a>
</p>
</form>
</div>
<div class="card domain-mapping-card">
<h2><?php _e('DNS Setup Instructions', 'wp-domain-mapping'); ?></h2>
<div class="dns-instructions">
<?php if (!empty($dm_cname)) : ?>
<h3><?php _e('CNAME Method (Recommended)', 'wp-domain-mapping'); ?></h3>
<p>
<?php
printf(
__('Tell your users to add a DNS "CNAME" record for their domain pointing to: %s', 'wp-domain-mapping'),
'<code>' . esc_html($dm_cname) . '</code>'
);
?>
</p>
<div class="dns-example">
<h4><?php _e('Example DNS Record', 'wp-domain-mapping'); ?></h4>
<table class="widefat striped">
<thead>
<tr>
<th><?php _e('Type', 'wp-domain-mapping'); ?></th>
<th><?php _e('Name', 'wp-domain-mapping'); ?></th>
<th><?php _e('Value', 'wp-domain-mapping'); ?></th>
</tr>
</thead>
<tbody>
<tr>
<td><code>CNAME</code></td>
<td><code>@</code> <?php _e('(or empty)', 'wp-domain-mapping'); ?></td>
<td><code><?php echo esc_html($dm_cname); ?></code></td>
</tr>
</tbody>
</table>
</div>
<?php endif; ?>
<?php if (!empty($dm_ipaddress)) : ?>
<h3><?php _e('A Record Method', 'wp-domain-mapping'); ?></h3>
<p>
<?php
printf(
__('Tell your users to add a DNS "A" record for their domain pointing to: %s', 'wp-domain-mapping'),
'<code>' . esc_html($dm_ipaddress) . '</code>'
);
?>
</p>
<div class="dns-example">
<h4><?php _e('Example DNS Record', 'wp-domain-mapping'); ?></h4>
<table class="widefat striped">
<thead>
<tr>
<th><?php _e('Type', 'wp-domain-mapping'); ?></th>
<th><?php _e('Name', 'wp-domain-mapping'); ?></th>
<th><?php _e('Value', 'wp-domain-mapping'); ?></th>
</tr>
</thead>
<tbody>
<?php
$ips = array_map('trim', explode(',', $dm_ipaddress));
foreach ($ips as $index => $ip) :
?>
<tr>
<td><code>A</code></td>
<td><code>@</code> <?php _e('(or empty)', 'wp-domain-mapping'); ?></td>
<td><code><?php echo esc_html($ip); ?></code></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>
<?php if (empty($dm_ipaddress) && empty($dm_cname)) : ?>
<div class="notice notice-warning">
<p>
<?php _e('Please configure either a Server IP Address or CNAME to provide DNS setup instructions.', 'wp-domain-mapping'); ?>
</p>
</div>
<?php endif; ?>
<h3><?php _e('Additional DNS Tips', 'wp-domain-mapping'); ?></h3>
<ul class="dns-tips">
<li>
<?php _e('Most DNS changes take 24-48 hours to fully propagate worldwide.', 'wp-domain-mapping'); ?>
</li>
<li>
<?php _e('For "www" subdomain, create a separate CNAME record with "www" as the name pointing to the same value.', 'wp-domain-mapping'); ?>
</li>
<li>
<?php _e('If you\'re using Cloudflare or similar services, you may need to adjust proxy settings.', 'wp-domain-mapping'); ?>
</li>
<li>
<?php _e('For SSL to work properly, make sure your web server is configured with the appropriate SSL certificates for mapped domains.', 'wp-domain-mapping'); ?>
</li>
</ul>
</div>
</div>
<div class="card domain-mapping-card">
<h2><?php _e('Installation Check', 'wp-domain-mapping'); ?></h2>
<table class="widefat striped">
<tbody>
<tr>
<th><?php _e('Status', 'wp-domain-mapping'); ?></th>
<th><?php _e('Check', 'wp-domain-mapping'); ?></th>
<th><?php _e('Value', 'wp-domain-mapping'); ?></th>
</tr>
<tr>
<td>
<?php if (file_exists(WP_CONTENT_DIR . '/sunrise.php')) : ?>
<span class="dashicons dashicons-yes-alt" style="color: #46b450;"></span>
<?php else : ?>
<span class="dashicons dashicons-no-alt" style="color: #dc3232;"></span>
<?php endif; ?>
</td>
<td><?php _e('sunrise.php file', 'wp-domain-mapping'); ?></td>
<td>
<?php if (file_exists(WP_CONTENT_DIR . '/sunrise.php')) : ?>
<?php _e('Found', 'wp-domain-mapping'); ?>
<?php else : ?>
<?php
printf(
__('Not found - copy sunrise.php to %s', 'wp-domain-mapping'),
'<code>' . esc_html(WP_CONTENT_DIR) . '</code>'
);
?>
<?php endif; ?>
</td>
</tr>
<tr>
<td>
<?php if (defined('SUNRISE')) : ?>
<span class="dashicons dashicons-yes-alt" style="color: #46b450;"></span>
<?php else : ?>
<span class="dashicons dashicons-no-alt" style="color: #dc3232;"></span>
<?php endif; ?>
</td>
<td><?php _e('SUNRISE constant', 'wp-domain-mapping'); ?></td>
<td>
<?php if (defined('SUNRISE')) : ?>
<?php
printf(
__('Defined as: %s', 'wp-domain-mapping'),
'<code>' . esc_html(SUNRISE) . '</code>'
);
?>
<?php else : ?>
<?php _e('Not defined - add to wp-config.php: ', 'wp-domain-mapping'); ?>
<code>define( 'SUNRISE', 'on' );</code>
<?php endif; ?>
</td>
</tr>
<tr>
<td>
<?php if (defined('SUNRISE_LOADED')) : ?>
<span class="dashicons dashicons-yes-alt" style="color: #46b450;"></span>
<?php else : ?>
<span class="dashicons dashicons-no-alt" style="color: #dc3232;"></span>
<?php endif; ?>
</td>
<td><?php _e('SUNRISE_LOADED', 'wp-domain-mapping'); ?></td>
<td>
<?php if (defined('SUNRISE_LOADED')) : ?>
<?php _e('Loaded successfully', 'wp-domain-mapping'); ?>
<?php else : ?>
<?php
if (defined('SUNRISE')) {
_e('Not loaded - make sure SUNRISE is defined before the require_once() in wp-config.php', 'wp-domain-mapping');
} else {
_e('Not loaded - SUNRISE constant not defined', 'wp-domain-mapping');
}
?>
<?php endif; ?>
</td>
</tr>
<tr>
<td>
<?php if (!defined('COOKIE_DOMAIN')) : ?>
<span class="dashicons dashicons-yes-alt" style="color: #46b450;"></span>
<?php else : ?>
<span class="dashicons dashicons-no-alt" style="color: #dc3232;"></span>
<?php endif; ?>
</td>
<td><?php _e('COOKIE_DOMAIN', 'wp-domain-mapping'); ?></td>
<td>
<?php if (!defined('COOKIE_DOMAIN')) : ?>
<?php _e('Not defined (correct)', 'wp-domain-mapping'); ?>
<?php else : ?>
<?php
printf(
__('Defined as: %s - remove this from wp-config.php', 'wp-domain-mapping'),
'<code>' . esc_html(COOKIE_DOMAIN) . '</code>'
);
?>
<?php endif; ?>
</td>
</tr>
<tr>
<td>
<?php
global $wpdb;
$tables_exist = true;
foreach (array(
$wpdb->base_prefix . WP_DOMAIN_MAPPING_TABLE_DOMAINS,
$wpdb->base_prefix . WP_DOMAIN_MAPPING_TABLE_LOGINS,
$wpdb->base_prefix . WP_DOMAIN_MAPPING_TABLE_LOGS,
) as $table) {
if ($wpdb->get_var("SHOW TABLES LIKE '$table'") != $table) {
$tables_exist = false;
break;
}
}
?>
<?php if ($tables_exist) : ?>
<span class="dashicons dashicons-yes-alt" style="color: #46b450;"></span>
<?php else : ?>
<span class="dashicons dashicons-no-alt" style="color: #dc3232;"></span>
<?php endif; ?>
</td>
<td><?php _e('Database tables', 'wp-domain-mapping'); ?></td>
<td>
<?php if ($tables_exist) : ?>
<?php _e('All tables exist', 'wp-domain-mapping'); ?>
<?php else : ?>
<?php _e('Some tables are missing - deactivate and reactivate the plugin', 'wp-domain-mapping'); ?>
<?php endif; ?>
</td>
</tr>
<tr>
<td>
<?php if (is_multisite()) : ?>
<span class="dashicons dashicons-yes-alt" style="color: #46b450;"></span>
<?php else : ?>
<span class="dashicons dashicons-no-alt" style="color: #dc3232;"></span>
<?php endif; ?>
</td>
<td><?php _e('Multisite', 'wp-domain-mapping'); ?></td>
<td>
<?php if (is_multisite()) : ?>
<?php _e('Enabled', 'wp-domain-mapping'); ?>
<?php else : ?>
<?php _e('Not enabled - this plugin requires WordPress Multisite', 'wp-domain-mapping'); ?>
<?php endif; ?>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<?php
}
/**
* Render the settings page by calling both parts
*/
function dm_render_settings_page() {
// Get current options
$dm_ipaddress = get_site_option('dm_ipaddress', '');
$dm_cname = get_site_option('dm_cname', '');
$dm_remote_login = get_site_option('dm_remote_login', 1);
$dm_301_redirect = get_site_option('dm_301_redirect', 0);
$dm_redirect_admin = get_site_option('dm_redirect_admin', 1);
$dm_user_settings = get_site_option('dm_user_settings', 1);
$dm_no_primary_domain = get_site_option('dm_no_primary_domain', 0);
// Get core instance
$core = WP_Domain_Mapping_Core::get_instance();
// Call the first part of the function
dm_render_settings_page_continued($dm_301_redirect, $dm_redirect_admin, $dm_user_settings, $dm_no_primary_domain, $dm_ipaddress, $dm_cname, $core);
}
/**
* Render user domain mapping page
*/
function dm_render_user_page() {
global $wpdb;
$core = WP_Domain_Mapping_Core::get_instance();
$db = WP_Domain_Mapping_DB::get_instance();
$protocol = is_ssl() ? 'https://' : 'http://';
$domains = $db->get_domains_by_blog_id($wpdb->blogid);
// Display updated messages
if (isset($_GET['updated'])) {
echo '<div class="notice notice-success"><p>';
switch ($_GET['updated']) {
case 'add':
_e('Domain added successfully.', 'wp-domain-mapping');
break;
case 'exists':
_e('This domain is already mapped to a site.', 'wp-domain-mapping');
break;
case 'primary':
_e('Primary domain updated.', 'wp-domain-mapping');
break;
case 'del':
_e('Domain deleted successfully.', 'wp-domain-mapping');
break;
}
echo '</p></div>';
}
?>
<div class="wrap">
<h1><?php _e('Domain Mapping', 'wp-domain-mapping'); ?></h1>
<div class="card domain-mapping-card">
<h2><?php _e('Add New Domain', 'wp-domain-mapping'); ?></h2>
<form method="post" action="<?php echo esc_url(admin_url('tools.php?page=domainmapping')); ?>">
<?php wp_nonce_field('domain_mapping'); ?>
<input type="hidden" name="action" value="add" />
<table class="form-table">
<tr>
<th scope="row"><label for="domain"><?php _e('Domain', 'wp-domain-mapping'); ?></label></th>
<td>
<input name="domain" id="domain" type="text" value="" class="regular-text"
placeholder="example.com" pattern="^[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9]?\.[a-zA-Z]{2,}$" required />
<p class="description">
<?php _e('Enter the domain without http:// or https:// (e.g., example.com)', 'wp-domain-mapping'); ?>
</p>
</td>
</tr>
<tr>
<th scope="row"><?php _e('Primary Domain', 'wp-domain-mapping'); ?></th>
<td>
<fieldset>
<legend class="screen-reader-text"><?php _e('Primary Domain', 'wp-domain-mapping'); ?></legend>
<label for="primary">
<input name="primary" type="checkbox" id="primary" value="1" />
<?php _e('Set this domain as the primary domain for this site', 'wp-domain-mapping'); ?>
</label>
</fieldset>
</td>
</tr>
</table>
<p class="submit">
<input type="submit" name="submit" id="submit" class="button button-primary" value="<?php _e('Add Domain', 'wp-domain-mapping'); ?>" />
</p>
</form>
</div>
<?php if (!empty($domains)): ?>
<div class="card domain-mapping-card">
<h2><?php _e('Your Mapped Domains', 'wp-domain-mapping'); ?></h2>
<table class="wp-list-table widefat fixed striped domains-table">
<thead>
<tr>
<th><?php _e('Domain', 'wp-domain-mapping'); ?></th>
<th><?php _e('Primary', 'wp-domain-mapping'); ?></th>
<th><?php _e('Actions', 'wp-domain-mapping'); ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($domains as $domain): ?>
<tr>
<td>
<a href="<?php echo esc_url($protocol . $domain->domain); ?>" target="_blank">
<?php echo esc_html($domain->domain); ?>
<span class="dashicons dashicons-external" style="font-size: 14px; line-height: 1.3; opacity: 0.7;"></span>
</a>
</td>
<td>
<?php if ($domain->active == 1): ?>
<span class="dashicons dashicons-yes-alt" style="color: #46b450;"></span>
<span class="screen-reader-text"><?php _e('Yes', 'wp-domain-mapping'); ?></span>
<?php else: ?>
<a href="<?php echo wp_nonce_url(add_query_arg(
array('page' => 'domainmapping', 'action' => 'primary', 'domain' => $domain->domain),
admin_url('tools.php')
), 'domain_mapping'); ?>" class="button button-small">
<?php _e('Make Primary', 'wp-domain-mapping'); ?>
</a>
<?php endif; ?>
</td>
<td>
<?php if ($domain->active != 1): ?>
<a href="<?php echo wp_nonce_url(add_query_arg(
array('page' => 'domainmapping', 'action' => 'delete', 'domain' => $domain->domain),
admin_url('tools.php')
), 'delete' . $domain->domain); ?>" class="button button-small button-link-delete" onclick="return confirm('<?php _e('Are you sure you want to delete this domain?', 'wp-domain-mapping'); ?>');">
<?php _e('Delete', 'wp-domain-mapping'); ?>
</a>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>
<div class="card domain-mapping-card">
<h2><?php _e('DNS Configuration Instructions', 'wp-domain-mapping'); ?></h2>
<?php
$ipaddress = get_site_option('dm_ipaddress');
$cname = get_site_option('dm_cname');
if (!$ipaddress && !$cname): ?>
<div class="notice notice-error">
<p><?php _e('The site administrator has not configured the DNS settings. Please contact them for assistance.', 'wp-domain-mapping'); ?></p>
</div>
<?php else: ?>
<p><?php _e('To map your domain to this site, you need to update your DNS records with your domain registrar.', 'wp-domain-mapping'); ?></p>
<?php if ($cname): ?>
<h3><?php _e('CNAME Method (Recommended)', 'wp-domain-mapping'); ?></h3>
<p><?php printf(__('Create a CNAME record for your domain pointing to: <code>%s</code>', 'wp-domain-mapping'), esc_html($cname)); ?></p>
<?php endif; ?>
<?php if ($ipaddress): ?>
<h3><?php _e('A Record Method', 'wp-domain-mapping'); ?></h3>
<p><?php printf(__('Create an A record for your domain pointing to: <code>%s</code>', 'wp-domain-mapping'), esc_html($ipaddress)); ?></p>
<?php endif; ?>
<p class="description"><?php _e('DNS changes may take 24-48 hours to fully propagate across the internet.', 'wp-domain-mapping'); ?></p>
<?php endif; ?>
</div>
</div>
<?php
}
/**
* Render health page
*/
function dm_render_health_page() {
// Check permissions
if (!current_user_can('manage_network')) {
wp_die(__('You do not have sufficient permissions to access this page.', 'wp-domain-mapping'));
}
// Get all domains
global $wpdb;
$table = $wpdb->base_prefix . WP_DOMAIN_MAPPING_TABLE_DOMAINS;
$domains = $wpdb->get_results("
SELECT d.*, b.domain as original_domain, b.path
FROM {$table} d
JOIN {$wpdb->blogs} b ON d.blog_id = b.blog_id
ORDER BY d.blog_id ASC, d.active DESC
");
// Get health check results
$health_results = get_site_option('dm_domain_health_results', array());
// Display page
?>
<div class="wrap">
<h1><?php echo esc_html(get_admin_page_title()); ?></h1>
<?php
// Display success messages
if (isset($_GET['checked']) && $_GET['checked']) {
echo '<div class="notice notice-success is-dismissible"><p>' .
__('Domain health check completed.', 'wp-domain-mapping') .
'</p></div>';
}
if (isset($_GET['settings-updated']) && $_GET['settings-updated']) {
echo '<div class="notice notice-success is-dismissible"><p>' .
__('Settings saved.', 'wp-domain-mapping') .
'</p></div>';
}
?>
<div class="card domain-mapping-card">
<h2><?php _e('Domain Health Status', 'wp-domain-mapping'); ?></h2>
<p>
<form method="post" action="">
<?php wp_nonce_field('dm_manual_health_check', 'dm_manual_health_check_nonce'); ?>
<input type="hidden" name="dm_manual_health_check" value="1">
<input type="submit" class="button button-primary" value="<?php esc_attr_e('Check All Domains Now', 'wp-domain-mapping'); ?>">
</form>
</p>
<div class="tablenav top">
<div class="tablenav-pages">
<span class="displaying-num">
<?php
if (!empty($domains)) {
printf(
_n('%s domain', '%s domains', count($domains), 'wp-domain-mapping'),
number_format_i18n(count($domains))
);
} else {
_e('No domains found', 'wp-domain-mapping');
}
?>
</span>
</div>
<br class="clear">
</div>
<table class="wp-list-table widefat fixed striped domains-health-table">
<thead>
<tr>
<th class="column-domain"><?php _e('Domain', 'wp-domain-mapping'); ?></th>
<th class="column-site"><?php _e('Site', 'wp-domain-mapping'); ?></th>
<th class="column-dns"><?php _e('DNS Status', 'wp-domain-mapping'); ?></th>
<th class="column-ssl"><?php _e('SSL Status', 'wp-domain-mapping'); ?></th>
<th class="column-status"><?php _e('Reachable', 'wp-domain-mapping'); ?></th>
<th class="column-last-check"><?php _e('Last Check', 'wp-domain-mapping'); ?></th>
<th class="column-actions"><?php _e('Actions', 'wp-domain-mapping'); ?></th>
</tr>
</thead>
<tbody>
<?php if (!empty($domains)) : ?>
<?php foreach ($domains as $domain) :
$domain_key = md5($domain->domain);
$health_data = isset($health_results[$domain_key]) ? $health_results[$domain_key] : null;
$site_name = get_blog_option($domain->blog_id, 'blogname', __('Unknown', 'wp-domain-mapping'));
?>
<tr data-domain="<?php echo esc_attr($domain->domain); ?>" data-blog-id="<?php echo esc_attr($domain->blog_id); ?>">
<td class="column-domain">
<?php echo esc_html($domain->domain); ?>
<?php if ($domain->active) : ?>
<span class="dashicons dashicons-star-filled" style="color: #f0b849;" title="<?php esc_attr_e('Primary Domain', 'wp-domain-mapping'); ?>"></span>
<?php endif; ?>
</td>
<td class="column-site">
<a href="<?php echo esc_url(network_admin_url('site-info.php?id=' . $domain->blog_id)); ?>">
<?php echo esc_html($site_name); ?>
<div class="row-actions">
<span class="original-domain"><?php echo esc_html($domain->original_domain . $domain->path); ?></span>
</div>
</a>
</td>
<td class="column-dns">
<?php if ($health_data && isset($health_data['dns_status'])) : ?>
<?php if ($health_data['dns_status'] === 'success') : ?>
<span class="dashicons dashicons-yes-alt" style="color: #46b450;" title="<?php esc_attr_e('DNS correctly configured', 'wp-domain-mapping'); ?>"></span>
<?php else : ?>
<span class="dashicons dashicons-warning" style="color: #dc3232;" title="<?php echo esc_attr($health_data['dns_message']); ?>"></span>
<?php endif; ?>
<?php else : ?>
<span class="dashicons dashicons-minus" style="color: #999;" title="<?php esc_attr_e('Not checked yet', 'wp-domain-mapping'); ?>"></span>
<?php endif; ?>
</td>
<td class="column-ssl">
<?php if ($health_data && isset($health_data['ssl_valid'])) : ?>
<?php if ($health_data['ssl_valid']) : ?>
<span class="dashicons dashicons-yes-alt" style="color: #46b450;" title="<?php esc_attr_e('SSL certificate valid', 'wp-domain-mapping'); ?>"></span>
<div class="row-actions">
<span><?php echo esc_html(sprintf(__('Expires: %s', 'wp-domain-mapping'), isset($health_data['ssl_expiry']) ? date('Y-m-d', strtotime($health_data['ssl_expiry'])) : '-')); ?></span>
</div>
<?php else : ?>
<span class="dashicons dashicons-warning" style="color: #dc3232;" title="<?php esc_attr_e('SSL certificate issue', 'wp-domain-mapping'); ?>"></span>
<?php endif; ?>
<?php else : ?>
<span class="dashicons dashicons-minus" style="color: #999;" title="<?php esc_attr_e('Not checked yet', 'wp-domain-mapping'); ?>"></span>
<?php endif; ?>
</td>
<td class="column-status">
<?php if ($health_data && isset($health_data['accessible'])) : ?>
<?php if ($health_data['accessible']) : ?>
<span class="dashicons dashicons-yes-alt" style="color: #46b450;" title="<?php esc_attr_e('Site is accessible', 'wp-domain-mapping'); ?>"></span>
<?php else : ?>
<span class="dashicons dashicons-warning" style="color: #dc3232;" title="<?php esc_attr_e('Site is not accessible', 'wp-domain-mapping'); ?>"></span>
<?php endif; ?>
<?php else : ?>
<span class="dashicons dashicons-minus" style="color: #999;" title="<?php esc_attr_e('Not checked yet', 'wp-domain-mapping'); ?>"></span>
<?php endif; ?>
</td>
<td class="column-last-check">
<?php
if ($health_data && isset($health_data['last_check'])) {
echo esc_html(human_time_diff(strtotime($health_data['last_check']), current_time('timestamp'))) . ' ' . __('ago', 'wp-domain-mapping');
} else {
_e('Never', 'wp-domain-mapping');
}
?>
</td>
<td class="column-actions">
<button type="button" class="button button-small check-domain-health" data-domain="<?php echo esc_attr($domain->domain); ?>">
<?php _e('Check Now', 'wp-domain-mapping'); ?>
</button>
<?php if ($health_data) : ?>
<button type="button" class="button button-small show-health-details" data-domain="<?php echo esc_attr($domain->domain); ?>">
<?php _e('Details', 'wp-domain-mapping'); ?>
</button>
<?php endif; ?>
</td>
</tr>
<?php if ($health_data) : ?>
<tr class="health-details-row" id="health-details-<?php echo esc_attr($domain_key); ?>" style="display: none;">
<td colspan="7">
<div class="health-details-content">
<h4><?php echo sprintf(__('Health Details for %s', 'wp-domain-mapping'), esc_html($domain->domain)); ?></h4>
<table class="widefat striped" style="margin-top: 10px;">
<tbody>
<tr>
<th><?php _e('Last Check', 'wp-domain-mapping'); ?></th>
<td><?php echo isset($health_data['last_check']) ? esc_html(date('Y-m-d H:i:s', strtotime($health_data['last_check']))) : '-'; ?></td>
</tr>
<tr>
<th><?php _e('DNS Status', 'wp-domain-mapping'); ?></th>
<td>
<?php if (isset($health_data['dns_status'])) : ?>
<?php if ($health_data['dns_status'] === 'success') : ?>
<span class="dashicons dashicons-yes-alt" style="color: #46b450;"></span>
<?php _e('DNS correctly configured', 'wp-domain-mapping'); ?>
<?php else : ?>
<span class="dashicons dashicons-warning" style="color: #dc3232;"></span>
<?php echo esc_html($health_data['dns_message']); ?>
<?php endif; ?>
<?php else : ?>
<?php _e('Not checked', 'wp-domain-mapping'); ?>
<?php endif; ?>
</td>
</tr>
<tr>
<th><?php _e('Resolved IP', 'wp-domain-mapping'); ?></th>
<td><?php echo isset($health_data['resolved_ip']) ? esc_html($health_data['resolved_ip']) : '-'; ?></td>
</tr>
<tr>
<th><?php _e('SSL Valid', 'wp-domain-mapping'); ?></th>
<td>
<?php if (isset($health_data['ssl_valid'])) : ?>
<?php if ($health_data['ssl_valid']) : ?>
<span class="dashicons dashicons-yes-alt" style="color: #46b450;"></span>
<?php _e('Valid', 'wp-domain-mapping'); ?>
<?php else : ?>
<span class="dashicons dashicons-warning" style="color: #dc3232;"></span>
<?php _e('Invalid', 'wp-domain-mapping'); ?>
<?php endif; ?>
<?php else : ?>
<?php _e('Not checked', 'wp-domain-mapping'); ?>
<?php endif; ?>
</td>
</tr>
<tr>
<th><?php _e('SSL Expiry', 'wp-domain-mapping'); ?></th>
<td><?php echo isset($health_data['ssl_expiry']) ? esc_html(date('Y-m-d', strtotime($health_data['ssl_expiry']))) : '-'; ?></td>
</tr>
<tr>
<th><?php _e('Response Code', 'wp-domain-mapping'); ?></th>
<td>
<?php
if (isset($health_data['response_code'])) {
echo esc_html($health_data['response_code']);
if ($health_data['response_code'] >= 200 && $health_data['response_code'] < 400) {
echo ' <span class="dashicons dashicons-yes-alt" style="color: #46b450;"></span>';
} else {
echo ' <span class="dashicons dashicons-warning" style="color: #dc3232;"></span>';
}
} else {
echo '-';
}
?>
</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
<?php endif; ?>
<?php endforeach; ?>
<?php else : ?>
<tr>
<td colspan="7"><?php _e('No domains found.', 'wp-domain-mapping'); ?></td>
</tr>
<?php endif; ?>
</tbody>
</table>
</div>
<div class="card domain-mapping-card">
<h2><?php _e('Health Check Settings', 'wp-domain-mapping'); ?></h2>
<form method="post" action="">
<?php wp_nonce_field('dm_health_settings', 'dm_health_settings_nonce'); ?>
<input type="hidden" name="dm_health_settings" value="1">
<table class="form-table" role="presentation">
<tr>
<th scope="row"><?php _e('Automatic Health Checks', 'wp-domain-mapping'); ?></th>
<td>
<fieldset>
<legend class="screen-reader-text"><span><?php _e('Automatic Health Checks', 'wp-domain-mapping'); ?></span></legend>
<label for="health_check_enabled">
<input name="health_check_enabled" type="checkbox" id="health_check_enabled" value="1" <?php checked(get_site_option('dm_health_check_enabled', true)); ?>>
<?php _e('Enable automatic daily health checks', 'wp-domain-mapping'); ?>
</label>
</fieldset>
</td>
</tr>
<tr>
<th scope="row"><?php _e('Email Notifications', 'wp-domain-mapping'); ?></th>
<td>
<fieldset>
<legend class="screen-reader-text"><span><?php _e('Email Notifications', 'wp-domain-mapping'); ?></span></legend>
<label for="health_notifications_enabled">
<input name="health_notifications_enabled" type="checkbox" id="health_notifications_enabled" value="1" <?php checked(get_site_option('dm_health_notifications_enabled', true)); ?>>
<?php _e('Send email notifications when domain health issues are detected', 'wp-domain-mapping'); ?>
</label>
</fieldset>
</td>
</tr>
<tr>
<th scope="row"><label for="notification_email"><?php _e('Notification Email', 'wp-domain-mapping'); ?></label></th>
<td>
<input name="notification_email" type="email" id="notification_email" class="regular-text" value="<?php echo esc_attr(get_site_option('dm_notification_email', get_option('admin_email'))); ?>">
<p class="description"><?php _e('Email address for domain health notifications.', 'wp-domain-mapping'); ?></p>
</td>
</tr>
<tr>
<th scope="row"><label for="ssl_expiry_threshold"><?php _e('SSL Expiry Warning', 'wp-domain-mapping'); ?></label></th>
<td>
<input name="ssl_expiry_threshold" type="number" id="ssl_expiry_threshold" min="1" max="90" class="small-text" value="<?php echo esc_attr(get_site_option('dm_ssl_expiry_threshold', 14)); ?>">
<span><?php _e('days', 'wp-domain-mapping'); ?></span>
<p class="description"><?php _e('Send notifications when SSL certificates are expiring within this many days.', 'wp-domain-mapping'); ?></p>
</td>
</tr>
</table>
<p class="submit">
<input type="submit" name="submit" id="submit" class="button button-primary" value="<?php esc_attr_e('Save Changes', 'wp-domain-mapping'); ?>">
</p>
</form>
</div>
</div>
<?php
}
/**
* Render import/export page
*/
function dm_render_import_export_page() {
// Check permissions
if (!current_user_can('manage_network')) {
wp_die(__('You do not have sufficient permissions to access this page.', 'wp-domain-mapping'));
}
// Output success messages
if (isset($_GET['imported']) && $_GET['imported']) {
$count = intval($_GET['imported']);
echo '<div class="notice notice-success is-dismissible"><p>' .
sprintf(
_n(
'%d domain mapping imported successfully.',
'%d domain mappings imported successfully.',
$count,
'wp-domain-mapping'
),
$count
) .
'</p></div>';
}
if (isset($_GET['export']) && $_GET['export'] == 'success') {
echo '<div class="notice notice-success is-dismissible"><p>' .
__('Domain mappings exported successfully.', 'wp-domain-mapping') .
'</p></div>';
}
?>
<div class="wrap">
<h1><?php echo esc_html(get_admin_page_title()); ?></h1>
<div class="card domain-mapping-card">
<h2><?php _e('Export Domain Mappings', 'wp-domain-mapping'); ?></h2>
<p><?php _e('Export all domain mappings to a CSV file.', 'wp-domain-mapping'); ?></p>
<form method="post" action="">
<?php wp_nonce_field('domain_mapping_export', 'domain_mapping_export_nonce'); ?>
<input type="hidden" name="domain_mapping_export" value="1">
<div style="margin-bottom: 15px;">
<label>
<input type="checkbox" name="include_header" value="1" checked>
<?php _e('Include column headers', 'wp-domain-mapping'); ?>
</label>
</div>
<div style="margin-bottom: 15px;">
<label for="blog_id_filter"><?php _e('Export for specific site ID (optional):', 'wp-domain-mapping'); ?></label>
<input type="number" id="blog_id_filter" name="blog_id_filter" min="1" class="regular-text">
<p class="description"><?php _e('Leave empty to export all domains.', 'wp-domain-mapping'); ?></p>
</div>
<p>
<input type="submit" class="button button-primary" value="<?php esc_attr_e('Export to CSV', 'wp-domain-mapping'); ?>">
</p>
</form>
</div>
<div class="card domain-mapping-card">
<h2><?php _e('Import Domain Mappings', 'wp-domain-mapping'); ?></h2>
<p><?php _e('Import domain mappings from a CSV file.', 'wp-domain-mapping'); ?></p>
<form method="post" enctype="multipart/form-data" id="domain-mapping-import-form">
<?php wp_nonce_field('domain_mapping_import', 'domain_mapping_import_nonce'); ?>
<input type="hidden" name="domain_mapping_import" value="1">
<div style="margin-bottom: 15px;">
<label for="csv_file"><?php _e('CSV File:', 'wp-domain-mapping'); ?></label><br>
<input type="file" id="csv_file" name="csv_file" accept=".csv" required>
<p class="description">
<?php _e('The CSV file should have the columns: blog_id, domain, active (1 or 0).', 'wp-domain-mapping'); ?><br>
<?php _e('Example: 1,example.com,1', 'wp-domain-mapping'); ?>
</p>
</div>
<div style="margin-bottom: 15px;">
<label>
<input type="checkbox" name="has_header" value="1" checked>
<?php _e('First row contains column headers', 'wp-domain-mapping'); ?>
</label>
</div>
<div style="margin-bottom: 15px;">
<label>
<input type="checkbox" name="update_existing" value="1" checked>
<?php _e('Update existing mappings', 'wp-domain-mapping'); ?>
</label>
<p class="description"><?php _e('If unchecked, will skip domains that already exist.', 'wp-domain-mapping'); ?></p>
</div>
<div style="margin-bottom: 15px;">
<label>
<input type="checkbox" name="validate_sites" value="1" checked>
<?php _e('Validate site IDs', 'wp-domain-mapping'); ?>
</label>
<p class="description"><?php _e('If checked, will only import domains for existing sites.', 'wp-domain-mapping'); ?></p>
</div>
<p>
<input type="submit" class="button button-primary" value="<?php esc_attr_e('Import from CSV', 'wp-domain-mapping'); ?>">
</p>
</form>
<div id="import-progress" style="display: none; margin-top: 20px;">
<p><?php _e('Processing import...', 'wp-domain-mapping'); ?></p>
<div class="progress-bar-outer" style="background-color: #f0f0f1; border-radius: 4px; height: 20px; width: 100%; overflow: hidden;">
<div class="progress-bar-inner" style="background-color: #2271b1; height: 100%; width: 0%;"></div>
</div>
<p class="progress-text">0%</p>
</div>
<div id="import-results" style="display: none; margin-top: 20px;">
<h3><?php _e('Import Results', 'wp-domain-mapping'); ?></h3>
<div class="import-summary"></div>
<div class="import-details"></div>
</div>
</div>
<div class="card domain-mapping-card">
<h2><?php _e('CSV Format', 'wp-domain-mapping'); ?></h2>
<p><?php _e('The CSV file should follow this format:', 'wp-domain-mapping'); ?></p>
<table class="widefat" style="margin-top: 10px;">
<thead>
<tr>
<th>blog_id</th>
<th>domain</th>
<th>active</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>example.com</td>
<td>1</td>
</tr>
<tr>
<td>2</td>
<td>example.org</td>
<td>0</td>
</tr>
</tbody>
</table>
<ul style="margin-top: 15px;">
<li><strong>blog_id</strong>: <?php _e('The ID of the WordPress site (required)', 'wp-domain-mapping'); ?></li>
<li><strong>domain</strong>: <?php _e('The domain name without http:// or https:// (required)', 'wp-domain-mapping'); ?></li>
<li><strong>active</strong>: <?php _e('Set to 1 to make this the primary domain, 0 otherwise (required)', 'wp-domain-mapping'); ?></li>
</ul>
</div>
</div>
<?php
}

183
admin/user-page.php Normal file
View file

@ -0,0 +1,183 @@
<?php
/**
* User domain mapping management page
*
* @package WP Domain Mapping
*/
defined('ABSPATH') || exit;
$protocol = isset($protocol) ? $protocol : (is_ssl() ? 'https://' : 'http://');
$domains = isset($domains) ? $domains : array();
// Initialize logs array if not set to prevent PHP warnings
if (!isset($logs) || !is_array($logs)) {
$logs = array();
}
?>
<div class="wrap">
<h1><?php _e('Domain Mapping', 'wp-domain-mapping'); ?></h1>
<?php if (isset($_GET['updated'])): ?>
<div class="notice notice-success">
<p>
<?php
switch ($_GET['updated']) {
case 'add':
_e('Domain added successfully.', 'wp-domain-mapping');
break;
case 'exists':
_e('This domain is already mapped to a site.', 'wp-domain-mapping');
break;
case 'primary':
_e('Primary domain updated.', 'wp-domain-mapping');
break;
case 'del':
_e('Domain deleted successfully.', 'wp-domain-mapping');
break;
default:
break;
}
?>
</p>
</div>
<?php endif; ?>
<div class="card domain-mapping-card">
<h2><?php _e('Add New Domain', 'wp-domain-mapping'); ?></h2>
<form method="post" action="<?php echo esc_url(admin_url('tools.php?page=domainmapping')); ?>">
<?php wp_nonce_field('domain_mapping'); ?>
<input type="hidden" name="action" value="add" />
<table class="form-table">
<tr>
<th scope="row"><label for="domain"><?php _e('Domain', 'wp-domain-mapping'); ?></label></th>
<td>
<input name="domain" id="domain" type="text" value="" class="regular-text"
placeholder="example.com" pattern="^[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9]?\.[a-zA-Z]{2,}$" required />
<p class="description">
<?php _e('Enter the domain without http:// or https:// (e.g., example.com)', 'wp-domain-mapping'); ?>
</p>
</td>
</tr>
<tr>
<th scope="row"><?php _e('Primary Domain', 'wp-domain-mapping'); ?></th>
<td>
<fieldset>
<legend class="screen-reader-text"><?php _e('Primary Domain', 'wp-domain-mapping'); ?></legend>
<label for="primary">
<input name="primary" type="checkbox" id="primary" value="1" />
<?php _e('Set this domain as the primary domain for this site', 'wp-domain-mapping'); ?>
</label>
</fieldset>
</td>
</tr>
</table>
<p class="submit">
<input type="submit" name="submit" id="submit" class="button button-primary" value="<?php _e('Add Domain', 'wp-domain-mapping'); ?>" />
</p>
</form>
</div>
<?php if (!empty($domains)): ?>
<div class="card domain-mapping-card">
<h2><?php _e('Your Mapped Domains', 'wp-domain-mapping'); ?></h2>
<table class="wp-list-table widefat fixed striped domains-table">
<thead>
<tr>
<th><?php _e('Domain', 'wp-domain-mapping'); ?></th>
<th><?php _e('Primary', 'wp-domain-mapping'); ?></th>
<th><?php _e('Actions', 'wp-domain-mapping'); ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($domains as $domain): ?>
<tr>
<td>
<a href="<?php echo esc_url($protocol . $domain['domain']); ?>" target="_blank">
<?php echo esc_html($domain['domain']); ?>
<span class="dashicons dashicons-external" style="font-size: 14px; line-height: 1.3; opacity: 0.7;"></span>
</a>
</td>
<td>
<?php if ($domain['active'] == 1): ?>
<span class="dashicons dashicons-yes-alt" style="color: #46b450;"></span>
<span class="screen-reader-text"><?php _e('Yes', 'wp-domain-mapping'); ?></span>
<?php else: ?>
<a href="<?php echo wp_nonce_url(add_query_arg(
array('page' => 'domainmapping', 'action' => 'primary', 'domain' => $domain['domain']),
admin_url('tools.php')
), 'domain_mapping'); ?>" class="button button-small">
<?php _e('Make Primary', 'wp-domain-mapping'); ?>
</a>
<?php endif; ?>
</td>
<td>
<?php if ($domain['active'] != 1): ?>
<a href="<?php echo wp_nonce_url(add_query_arg(
array('page' => 'domainmapping', 'action' => 'delete', 'domain' => $domain['domain']),
admin_url('tools.php')
), 'delete' . $domain['domain']); ?>" class="button button-small button-link-delete" onclick="return confirm('<?php _e('Are you sure you want to delete this domain?', 'wp-domain-mapping'); ?>');">
<?php _e('Delete', 'wp-domain-mapping'); ?>
</a>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>
<div class="card domain-mapping-card">
<h2><?php _e('DNS Configuration Instructions', 'wp-domain-mapping'); ?></h2>
<?php
$ipaddress = get_site_option('dm_ipaddress');
$cname = get_site_option('dm_cname');
if (!$ipaddress && !$cname): ?>
<div class="notice notice-error">
<p><?php _e('The site administrator has not configured the DNS settings. Please contact them for assistance.', 'wp-domain-mapping'); ?></p>
</div>
<?php else: ?>
<p><?php _e('To map your domain to this site, you need to update your DNS records with your domain registrar.', 'wp-domain-mapping'); ?></p>
<?php if ($cname): ?>
<h3><?php _e('CNAME Method (Recommended)', 'wp-domain-mapping'); ?></h3>
<p><?php printf(__('Create a CNAME record for your domain pointing to: <code>%s</code>', 'wp-domain-mapping'), esc_html($cname)); ?></p>
<?php endif; ?>
<?php if ($ipaddress): ?>
<h3><?php _e('A Record Method', 'wp-domain-mapping'); ?></h3>
<p><?php printf(__('Create an A record for your domain pointing to: <code>%s</code>', 'wp-domain-mapping'), esc_html($ipaddress)); ?></p>
<?php endif; ?>
<p class="description"><?php _e('DNS changes may take 24-48 hours to fully propagate across the internet.', 'wp-domain-mapping'); ?></p>
<?php endif; ?>
</div>
</div>
<style>
/* Main cards */
.domain-mapping-card {
background: #fff;
border: 1px solid #ccd0d4;
border-radius: 4px;
margin-top: 20px;
padding: 20px;
box-shadow: 0 1px 1px rgba(0,0,0,.04);
}
.domains-table .column-primary {
width: 150px;
text-align: center;
}
.domains-table .column-actions {
width: 120px;
}
</style>