admin_url( 'admin-ajax.php' ),
'nonce' => wp_create_nonce( 'woocow_admin' ),
] );
}
// ── Page: Dashboard ──────────────────────────────────────────────────────
public function page_dashboard(): void {
global $wpdb;
$servers = (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->prefix}woocow_servers WHERE active=1" );
$assignments = (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->prefix}woocow_assignments" );
$customers = (int) $wpdb->get_var( "SELECT COUNT(DISTINCT customer_id) FROM {$wpdb->prefix}woocow_assignments" );
?>
WooCow – Servers
Add your Mailcow server instances here. The API key must be a read-write key from Configuration → Access → Edit administrator details → API .
+ Add Server
WooCow – Domain Assignments
Assign one or more Mailcow domains to a WooCommerce customer. The customer can then manage mailboxes for those domains from My Account → Email Hosting .
Current Assignments
Loading…
get_results( "SELECT id, name FROM {$wpdb->prefix}woocow_servers WHERE active=1 ORDER BY name" );
?>
WooCow – Mailboxes
— Select server —
name ); ?>
— Select domain —
Load Mailboxes
+ Create Mailbox
Create Mailbox
Create
Cancel
get_row( $wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}woocow_servers WHERE id = %d",
$id
) );
}
private function json_ok( $data = null ): void {
wp_send_json_success( $data );
}
private function json_err( string $msg ): void {
wp_send_json_error( $msg );
}
// ── AJAX: Servers ─────────────────────────────────────────────────────────
public function ajax_woocow_servers_list(): void {
$this->verify();
global $wpdb;
$rows = $wpdb->get_results( "SELECT id, name, url, active, created_at FROM {$wpdb->prefix}woocow_servers ORDER BY name" );
$this->json_ok( $rows );
}
public function ajax_woocow_server_save(): void {
$this->verify();
global $wpdb;
$id = absint( $_POST['id'] ?? 0 );
$name = sanitize_text_field( $_POST['name'] ?? '' );
$url = esc_url_raw( $_POST['url'] ?? '' );
$key = sanitize_text_field( $_POST['api_key'] ?? '' );
$active = absint( $_POST['active'] ?? 1 );
if ( ! $name || ! $url || ! $key ) {
$this->json_err( 'Name, URL, and API key are required.' );
}
$data = compact( 'name', 'url', 'active' ) + [ 'api_key' => $key ];
if ( $id ) {
$wpdb->update( "{$wpdb->prefix}woocow_servers", $data, [ 'id' => $id ] );
$this->json_ok( [ 'id' => $id ] );
} else {
$wpdb->insert( "{$wpdb->prefix}woocow_servers", $data );
$this->json_ok( [ 'id' => $wpdb->insert_id ] );
}
}
public function ajax_woocow_server_delete(): void {
$this->verify();
global $wpdb;
$id = absint( $_POST['id'] ?? 0 );
$wpdb->delete( "{$wpdb->prefix}woocow_servers", [ 'id' => $id ] );
$wpdb->delete( "{$wpdb->prefix}woocow_assignments", [ 'server_id' => $id ] );
$this->json_ok();
}
public function ajax_woocow_server_test(): void {
$this->verify();
$id = absint( $_POST['id'] ?? 0 );
// Allow testing before saving (pass url+key directly)
if ( $id ) {
$server = $this->get_server( $id );
if ( ! $server ) {
$this->json_err( 'Server not found.' );
}
$api = WooCow_API::from_server( $server );
} else {
$url = esc_url_raw( $_POST['url'] ?? '' );
$key = sanitize_text_field( $_POST['api_key'] ?? '' );
if ( ! $url || ! $key ) {
$this->json_err( 'URL and API key required.' );
}
$api = new WooCow_API( $url, $key );
}
$result = $api->test_connection();
if ( $result['success'] ) {
$version = $result['data']['version'] ?? $result['data'][0]['version'] ?? 'unknown';
$this->json_ok( [ 'version' => $version ] );
} else {
$this->json_err( $result['error'] ?? 'Connection failed.' );
}
}
public function ajax_woocow_server_domains(): void {
$this->verify();
$id = absint( $_POST['server_id'] ?? 0 );
$server = $this->get_server( $id );
if ( ! $server ) {
$this->json_err( 'Server not found.' );
}
$api = WooCow_API::from_server( $server );
$result = $api->get_domains();
if ( ! $result['success'] ) {
$this->json_err( $result['error'] ?? 'Failed to fetch domains.' );
}
$domains = array_map( fn( $d ) => [ 'domain' => $d['domain_name'], 'active' => $d['active'] ], (array) $result['data'] );
$this->json_ok( $domains );
}
// ── AJAX: Assignments ─────────────────────────────────────────────────────
public function ajax_woocow_assignments_list(): void {
$this->verify();
global $wpdb;
$rows = $wpdb->get_results( "
SELECT a.id, a.customer_id, a.domain, a.created_at,
s.name AS server_name, s.url AS server_url,
u.display_name, u.user_email
FROM {$wpdb->prefix}woocow_assignments a
JOIN {$wpdb->prefix}woocow_servers s ON s.id = a.server_id
JOIN {$wpdb->users} u ON u.ID = a.customer_id
ORDER BY u.display_name, a.domain
" );
$this->json_ok( $rows );
}
public function ajax_woocow_assignment_save(): void {
$this->verify();
global $wpdb;
$customer_id = absint( $_POST['customer_id'] ?? 0 );
$server_id = absint( $_POST['server_id'] ?? 0 );
$domain = sanitize_text_field( $_POST['domain'] ?? '' );
if ( ! $customer_id || ! $server_id || ! $domain ) {
$this->json_err( 'Customer, server, and domain are all required.' );
}
$existing = $wpdb->get_var( $wpdb->prepare(
"SELECT id FROM {$wpdb->prefix}woocow_assignments WHERE customer_id=%d AND domain=%s",
$customer_id, $domain
) );
if ( $existing ) {
$this->json_err( 'This domain is already assigned to this customer.' );
}
$wpdb->insert( "{$wpdb->prefix}woocow_assignments", compact( 'customer_id', 'server_id', 'domain' ) );
$this->json_ok( [ 'id' => $wpdb->insert_id ] );
}
public function ajax_woocow_assignment_delete(): void {
$this->verify();
global $wpdb;
$id = absint( $_POST['id'] ?? 0 );
$wpdb->delete( "{$wpdb->prefix}woocow_assignments", [ 'id' => $id ] );
$this->json_ok();
}
// ── AJAX: Customer search ─────────────────────────────────────────────────
public function ajax_woocow_customers_search(): void {
$this->verify();
$term = sanitize_text_field( $_POST['term'] ?? '' );
if ( strlen( $term ) < 2 ) {
$this->json_ok( [] );
}
$users = get_users( [
'search' => '*' . $term . '*',
'search_columns' => [ 'user_login', 'user_email', 'display_name' ],
'role__in' => [ 'customer', 'subscriber', 'administrator', 'shop_manager' ],
'number' => 15,
] );
$out = array_map( fn( $u ) => [
'id' => $u->ID,
'label' => sprintf( '%s (%s)', $u->display_name, $u->user_email ),
], $users );
$this->json_ok( $out );
}
// ── AJAX: Admin Mailboxes ─────────────────────────────────────────────────
public function ajax_woocow_admin_mailboxes(): void {
$this->verify();
$server_id = absint( $_POST['server_id'] ?? 0 );
$domain = sanitize_text_field( $_POST['domain'] ?? '' );
$server = $this->get_server( $server_id );
if ( ! $server ) {
$this->json_err( 'Server not found.' );
}
$api = WooCow_API::from_server( $server );
$result = $domain
? $api->get_domain_mailboxes( $domain )
: $api->get_all_mailboxes();
if ( ! $result['success'] ) {
$this->json_err( $result['error'] ?? 'Failed to fetch mailboxes.' );
}
$this->json_ok( [
'mailboxes' => $result['data'] ?? [],
'webmail_url' => $api->get_webmail_url(),
] );
}
public function ajax_woocow_admin_mailbox_create(): void {
$this->verify();
$server_id = absint( $_POST['server_id'] ?? 0 );
$domain = sanitize_text_field( $_POST['domain'] ?? '' );
$local_part = sanitize_text_field( $_POST['local_part'] ?? '' );
$name = sanitize_text_field( $_POST['name'] ?? '' );
$password = $_POST['password'] ?? '';
$password2 = $_POST['password2'] ?? '';
$quota = absint( $_POST['quota'] ?? 1024 );
if ( ! $domain || ! $local_part || ! $password ) {
$this->json_err( 'Domain, local part, and password are required.' );
}
if ( $password !== $password2 ) {
$this->json_err( 'Passwords do not match.' );
}
$server = $this->get_server( $server_id );
if ( ! $server ) {
$this->json_err( 'Server not found.' );
}
$api = WooCow_API::from_server( $server );
$result = $api->create_mailbox( [
'local_part' => $local_part,
'domain' => $domain,
'name' => $name ?: $local_part,
'password' => $password,
'password2' => $password2,
'quota' => $quota,
'active' => 1,
'force_pw_update' => 0,
'tls_enforce_in' => 0,
'tls_enforce_out' => 0,
] );
if ( ! $result['success'] ) {
$this->json_err( $result['error'] ?? 'Failed to create mailbox.' );
}
$this->json_ok( [ 'email' => $local_part . '@' . $domain ] );
}
public function ajax_woocow_admin_mailbox_delete(): void {
$this->verify();
$server_id = absint( $_POST['server_id'] ?? 0 );
$email = sanitize_email( $_POST['email'] ?? '' );
$server = $this->get_server( $server_id );
if ( ! $server ) {
$this->json_err( 'Server not found.' );
}
$api = WooCow_API::from_server( $server );
$result = $api->delete_mailbox( $email );
if ( ! $result['success'] ) {
$this->json_err( $result['error'] ?? 'Failed to delete mailbox.' );
}
$this->json_ok();
}
}