admin_url( 'admin-ajax.php' ), 'nonce' => wp_create_nonce( 'wooaapanel_admin' ), ] ); } // ── Pages ──────────────────────────────────────────────────────────────── public function page_dashboard(): void { echo '

WooAApanel

'; echo '

' . esc_html__( 'Manage aaPanel servers, site and database assignments for your WooCommerce customers.', 'wooaapanel' ) . '

'; echo '
'; } public function page_servers(): void { echo '

' . esc_html__( 'aaPanel Servers', 'wooaapanel' ) . '

'; echo '
'; } public function page_site_assignments(): void { echo '

' . esc_html__( 'Site Assignments', 'wooaapanel' ) . '

'; echo '
'; } public function page_db_assignments(): void { echo '

' . esc_html__( 'Database Assignments', 'wooaapanel' ) . '

'; echo '
'; } public function page_sites(): void { echo '

' . esc_html__( 'Sites', 'wooaapanel' ) . '

'; echo '
'; } public function page_databases(): void { echo '

' . esc_html__( 'Databases', 'wooaapanel' ) . '

'; echo '
'; } public function page_products(): void { echo '

' . esc_html__( 'WC Product ↔ Server Linking', 'wooaapanel' ) . '

'; echo '

' . esc_html__( 'Link a WooCommerce product to an aaPanel server. When a customer purchases the product, a site and database will be automatically provisioned on the linked server.', 'wooaapanel' ) . '

'; echo '
'; } // ── Helpers ─────────────────────────────────────────────────────────────── private function verify_admin(): void { check_ajax_referer( 'wooaapanel_admin', 'nonce' ); if ( ! current_user_can( 'manage_woocommerce' ) ) { wp_send_json_error( 'Insufficient permissions.', 403 ); } } private function get_server( int $id ): ?object { global $wpdb; return $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}wooaapanel_servers WHERE id = %d", $id ) ); } private function api( int $server_id ): WooAApanel_API { $server = $this->get_server( $server_id ); if ( ! $server ) { wp_send_json_error( 'Server not found.', 404 ); } return WooAApanel_API::from_server( $server ); } // ═════════════════════════════════════════════════════════════════════════ // AJAX: Servers // ═════════════════════════════════════════════════════════════════════════ public function ajax_wooaapanel_servers_list(): void { $this->verify_admin(); global $wpdb; $rows = $wpdb->get_results( "SELECT id, name, url, active, created_at FROM {$wpdb->prefix}wooaapanel_servers ORDER BY id DESC" ); wp_send_json_success( $rows ); } public function ajax_wooaapanel_server_save(): void { $this->verify_admin(); $id = absint( $_POST['id'] ?? 0 ); $name = sanitize_text_field( $_POST['name'] ?? '' ); $url = esc_url_raw( $_POST['url'] ?? '' ); $api_key = sanitize_text_field( $_POST['api_key'] ?? '' ); $active = absint( $_POST['active'] ?? 1 ); if ( ! $name || ! $url || ! $api_key ) { wp_send_json_error( 'Name, URL and API key are required.' ); } global $wpdb; $data = compact( 'name', 'url', 'api_key', 'active' ); if ( $id ) { $wpdb->update( "{$wpdb->prefix}wooaapanel_servers", $data, [ 'id' => $id ] ); } else { $wpdb->insert( "{$wpdb->prefix}wooaapanel_servers", $data ); $id = $wpdb->insert_id; } wp_send_json_success( [ 'id' => $id ] ); } public function ajax_wooaapanel_server_delete(): void { $this->verify_admin(); $id = absint( $_POST['id'] ?? 0 ); global $wpdb; $wpdb->delete( "{$wpdb->prefix}wooaapanel_servers", [ 'id' => $id ] ); wp_send_json_success(); } public function ajax_wooaapanel_server_test(): void { $this->verify_admin(); $id = absint( $_POST['id'] ?? 0 ); $api = $this->api( $id ); $res = $api->test_connection(); wp_send_json( $res ); } // ── Remote site/db lists (used by assignment UI) ────────────────────── public function ajax_wooaapanel_remote_sites(): void { $this->verify_admin(); $server_id = absint( $_POST['server_id'] ?? 0 ); $api = $this->api( $server_id ); $res = $api->get_sites( 1, 200 ); wp_send_json( $res ); } public function ajax_wooaapanel_remote_dbs(): void { $this->verify_admin(); $server_id = absint( $_POST['server_id'] ?? 0 ); $api = $this->api( $server_id ); $res = $api->get_databases( 1, 200 ); wp_send_json( $res ); } // ═════════════════════════════════════════════════════════════════════════ // AJAX: Site Assignments // ═════════════════════════════════════════════════════════════════════════ public function ajax_wooaapanel_site_assignments_list(): void { $this->verify_admin(); global $wpdb; $rows = $wpdb->get_results( " SELECT a.id, a.customer_id, a.server_id, a.site_name, a.domain, a.created_at, s.name AS server_name, u.display_name AS customer_name, u.user_email AS customer_email FROM {$wpdb->prefix}wooaapanel_site_assignments a JOIN {$wpdb->prefix}wooaapanel_servers s ON s.id = a.server_id LEFT JOIN {$wpdb->users} u ON u.ID = a.customer_id ORDER BY a.id DESC " ); wp_send_json_success( $rows ); } public function ajax_wooaapanel_site_assignment_save(): void { $this->verify_admin(); $id = absint( $_POST['id'] ?? 0 ); $customer_id = absint( $_POST['customer_id'] ?? 0 ); $server_id = absint( $_POST['server_id'] ?? 0 ); $site_name = sanitize_text_field( $_POST['site_name'] ?? '' ); $domain = sanitize_text_field( $_POST['domain'] ?? '' ); if ( ! $customer_id || ! $server_id || ! $site_name ) { wp_send_json_error( 'Customer, server and site name are required.' ); } global $wpdb; $data = compact( 'customer_id', 'server_id', 'site_name', 'domain' ); if ( $id ) { $wpdb->update( "{$wpdb->prefix}wooaapanel_site_assignments", $data, [ 'id' => $id ] ); } else { $wpdb->insert( "{$wpdb->prefix}wooaapanel_site_assignments", $data ); $id = $wpdb->insert_id; } wp_send_json_success( [ 'id' => $id ] ); } public function ajax_wooaapanel_site_assignment_delete(): void { $this->verify_admin(); $id = absint( $_POST['id'] ?? 0 ); global $wpdb; $wpdb->delete( "{$wpdb->prefix}wooaapanel_site_assignments", [ 'id' => $id ] ); wp_send_json_success(); } // ═════════════════════════════════════════════════════════════════════════ // AJAX: DB Assignments // ═════════════════════════════════════════════════════════════════════════ public function ajax_wooaapanel_db_assignments_list(): void { $this->verify_admin(); global $wpdb; $rows = $wpdb->get_results( " SELECT a.id, a.customer_id, a.server_id, a.db_name, a.created_at, s.name AS server_name, u.display_name AS customer_name, u.user_email AS customer_email FROM {$wpdb->prefix}wooaapanel_db_assignments a JOIN {$wpdb->prefix}wooaapanel_servers s ON s.id = a.server_id LEFT JOIN {$wpdb->users} u ON u.ID = a.customer_id ORDER BY a.id DESC " ); wp_send_json_success( $rows ); } public function ajax_wooaapanel_db_assignment_save(): void { $this->verify_admin(); $id = absint( $_POST['id'] ?? 0 ); $customer_id = absint( $_POST['customer_id'] ?? 0 ); $server_id = absint( $_POST['server_id'] ?? 0 ); $db_name = sanitize_text_field( $_POST['db_name'] ?? '' ); if ( ! $customer_id || ! $server_id || ! $db_name ) { wp_send_json_error( 'Customer, server and database name are required.' ); } global $wpdb; $data = compact( 'customer_id', 'server_id', 'db_name' ); if ( $id ) { $wpdb->update( "{$wpdb->prefix}wooaapanel_db_assignments", $data, [ 'id' => $id ] ); } else { $wpdb->insert( "{$wpdb->prefix}wooaapanel_db_assignments", $data ); $id = $wpdb->insert_id; } wp_send_json_success( [ 'id' => $id ] ); } public function ajax_wooaapanel_db_assignment_delete(): void { $this->verify_admin(); $id = absint( $_POST['id'] ?? 0 ); global $wpdb; $wpdb->delete( "{$wpdb->prefix}wooaapanel_db_assignments", [ 'id' => $id ] ); wp_send_json_success(); } // ═════════════════════════════════════════════════════════════════════════ // AJAX: Customer search // ═════════════════════════════════════════════════════════════════════════ public function ajax_wooaapanel_customers_search(): void { $this->verify_admin(); $q = sanitize_text_field( $_POST['q'] ?? '' ); $users = get_users( [ 'role__in' => [ 'customer', 'subscriber', 'administrator' ], 'search' => '*' . $q . '*', 'number' => 20, 'fields' => [ 'ID', 'display_name', 'user_email' ], ] ); wp_send_json_success( array_map( fn( $u ) => [ 'id' => $u->ID, 'label' => $u->display_name . ' <' . $u->user_email . '>', ], $users ) ); } // ═════════════════════════════════════════════════════════════════════════ // AJAX: Admin site actions (ALL operations) // ═════════════════════════════════════════════════════════════════════════ public function ajax_wooaapanel_admin_site_list(): void { $this->verify_admin(); $server_id = absint( $_POST['server_id'] ?? 0 ); $search = sanitize_text_field( $_POST['search'] ?? '' ); $api = $this->api( $server_id ); wp_send_json( $api->get_sites( 1, 100, $search ) ); } public function ajax_wooaapanel_admin_site_add(): void { $this->verify_admin(); $server_id = absint( $_POST['server_id'] ?? 0 ); $api = $this->api( $server_id ); $data = [ 'webname' => sanitize_text_field( $_POST['webname'] ?? '' ), 'path' => sanitize_text_field( $_POST['path'] ?? '' ), 'type_id' => absint( $_POST['type_id'] ?? 0 ), 'version' => sanitize_text_field( $_POST['version'] ?? '' ), 'port' => absint( $_POST['port'] ?? 80 ), 'ps' => sanitize_text_field( $_POST['ps'] ?? '' ), 'ftp_username' => sanitize_text_field( $_POST['ftp_username'] ?? '' ), 'ftp_password' => sanitize_text_field( $_POST['ftp_password'] ?? '' ), 'sql' => sanitize_text_field( $_POST['sql'] ?? '' ), 'codeing' => sanitize_text_field( $_POST['codeing'] ?? 'utf8mb4' ), 'datauser' => sanitize_text_field( $_POST['datauser'] ?? '' ), 'datapassword' => sanitize_text_field( $_POST['datapassword'] ?? '' ), ]; wp_send_json( $api->add_site( $data ) ); } public function ajax_wooaapanel_admin_site_delete(): void { $this->verify_admin(); $server_id = absint( $_POST['server_id'] ?? 0 ); $site_name = sanitize_text_field( $_POST['site_name'] ?? '' ); $ftp = ! empty( $_POST['ftp'] ); $database = ! empty( $_POST['database'] ); $path = ! empty( $_POST['path'] ); $api = $this->api( $server_id ); wp_send_json( $api->delete_site( $site_name, $ftp, $database, $path ) ); } public function ajax_wooaapanel_admin_site_domains(): void { $this->verify_admin(); $server_id = absint( $_POST['server_id'] ?? 0 ); $site_name = sanitize_text_field( $_POST['site_name'] ?? '' ); $api = $this->api( $server_id ); wp_send_json( $api->get_site_domains( $site_name ) ); } public function ajax_wooaapanel_admin_site_add_domain(): void { $this->verify_admin(); $server_id = absint( $_POST['server_id'] ?? 0 ); $site_name = sanitize_text_field( $_POST['site_name'] ?? '' ); $domain = sanitize_text_field( $_POST['domain'] ?? '' ); $api = $this->api( $server_id ); wp_send_json( $api->add_domain( $site_name, $domain ) ); } public function ajax_wooaapanel_admin_site_del_domain(): void { $this->verify_admin(); $server_id = absint( $_POST['server_id'] ?? 0 ); $site_name = sanitize_text_field( $_POST['site_name'] ?? '' ); $domain = sanitize_text_field( $_POST['domain'] ?? '' ); $site_id = absint( $_POST['site_id'] ?? 0 ); $api = $this->api( $server_id ); wp_send_json( $api->delete_domain( $site_name, $domain, $site_id ) ); } public function ajax_wooaapanel_admin_site_xss_get(): void { $this->verify_admin(); $server_id = absint( $_POST['server_id'] ?? 0 ); $site_name = sanitize_text_field( $_POST['site_name'] ?? '' ); $site_path = sanitize_text_field( $_POST['site_path'] ?? '' ); $api = $this->api( $server_id ); wp_send_json( $api->get_xss( $site_name, $site_path ) ); } public function ajax_wooaapanel_admin_site_xss_set(): void { $this->verify_admin(); $server_id = absint( $_POST['server_id'] ?? 0 ); $site_name = sanitize_text_field( $_POST['site_name'] ?? '' ); $site_path = sanitize_text_field( $_POST['site_path'] ?? '' ); $enable = ! empty( $_POST['enable'] ); $api = $this->api( $server_id ); wp_send_json( $api->set_xss( $site_name, $site_path, $enable ) ); } public function ajax_wooaapanel_admin_site_php_get(): void { $this->verify_admin(); $server_id = absint( $_POST['server_id'] ?? 0 ); $site_name = sanitize_text_field( $_POST['site_name'] ?? '' ); $api = $this->api( $server_id ); wp_send_json( $api->get_site_php_version( $site_name ) ); } public function ajax_wooaapanel_admin_site_php_versions(): void { $this->verify_admin(); $server_id = absint( $_POST['server_id'] ?? 0 ); $api = $this->api( $server_id ); wp_send_json( $api->get_php_versions() ); } public function ajax_wooaapanel_admin_site_php_set(): void { $this->verify_admin(); $server_id = absint( $_POST['server_id'] ?? 0 ); $site_name = sanitize_text_field( $_POST['site_name'] ?? '' ); $version = sanitize_text_field( $_POST['version'] ?? '' ); $api = $this->api( $server_id ); wp_send_json( $api->set_site_php_version( $site_name, $version ) ); } public function ajax_wooaapanel_admin_site_rewrite_list(): void { $this->verify_admin(); $server_id = absint( $_POST['server_id'] ?? 0 ); $site_name = sanitize_text_field( $_POST['site_name'] ?? '' ); $api = $this->api( $server_id ); wp_send_json( $api->get_rewrite_list( $site_name ) ); } public function ajax_wooaapanel_admin_site_rewrite_get(): void { $this->verify_admin(); $server_id = absint( $_POST['server_id'] ?? 0 ); $site_name = sanitize_text_field( $_POST['site_name'] ?? '' ); $template = sanitize_text_field( $_POST['template'] ?? '' ); $api = $this->api( $server_id ); wp_send_json( $api->get_rewrite_content( $site_name, $template ) ); } public function ajax_wooaapanel_admin_site_rewrite_set(): void { $this->verify_admin(); $server_id = absint( $_POST['server_id'] ?? 0 ); $site_name = sanitize_text_field( $_POST['site_name'] ?? '' ); $content = wp_unslash( $_POST['content'] ?? '' ); $api = $this->api( $server_id ); wp_send_json( $api->set_rewrite( $site_name, $content ) ); } public function ajax_wooaapanel_admin_site_ssl_get(): void { $this->verify_admin(); $server_id = absint( $_POST['server_id'] ?? 0 ); $site_name = sanitize_text_field( $_POST['site_name'] ?? '' ); $api = $this->api( $server_id ); wp_send_json( $api->get_ssl( $site_name ) ); } public function ajax_wooaapanel_admin_site_ssl_close(): void { $this->verify_admin(); $server_id = absint( $_POST['server_id'] ?? 0 ); $site_name = sanitize_text_field( $_POST['site_name'] ?? '' ); $api = $this->api( $server_id ); wp_send_json( $api->close_ssl( $site_name ) ); } public function ajax_wooaapanel_admin_site_ssl_list(): void { $this->verify_admin(); $server_id = absint( $_POST['server_id'] ?? 0 ); $api = $this->api( $server_id ); wp_send_json( $api->list_ssl_certs() ); } public function ajax_wooaapanel_admin_site_ssl_upload(): void { $this->verify_admin(); $server_id = absint( $_POST['server_id'] ?? 0 ); $key = wp_unslash( $_POST['key'] ?? '' ); $cert = wp_unslash( $_POST['cert'] ?? '' ); $domain = sanitize_text_field( $_POST['domain'] ?? '' ); $api = $this->api( $server_id ); wp_send_json( $api->upload_cert( $key, $cert, $domain ) ); } public function ajax_wooaapanel_admin_site_ssl_deploy(): void { $this->verify_admin(); $server_id = absint( $_POST['server_id'] ?? 0 ); $site_name = sanitize_text_field( $_POST['site_name'] ?? '' ); $cert_id = absint( $_POST['cert_id'] ?? 0 ); $api = $this->api( $server_id ); wp_send_json( $api->deploy_cert_to_site( $site_name, $cert_id ) ); } public function ajax_wooaapanel_admin_site_run_path(): void { $this->verify_admin(); $server_id = absint( $_POST['server_id'] ?? 0 ); $site_name = sanitize_text_field( $_POST['site_name'] ?? '' ); $run_path = sanitize_text_field( $_POST['run_path'] ?? '' ); $api = $this->api( $server_id ); wp_send_json( $api->set_run_path( $site_name, $run_path ) ); } // ═════════════════════════════════════════════════════════════════════════ // AJAX: Admin DB actions (ALL operations) // ═════════════════════════════════════════════════════════════════════════ public function ajax_wooaapanel_admin_db_list(): void { $this->verify_admin(); $server_id = absint( $_POST['server_id'] ?? 0 ); $search = sanitize_text_field( $_POST['search'] ?? '' ); $api = $this->api( $server_id ); wp_send_json( $api->get_databases( 1, 100, $search ) ); } public function ajax_wooaapanel_admin_db_add(): void { $this->verify_admin(); $server_id = absint( $_POST['server_id'] ?? 0 ); $db_name = sanitize_text_field( $_POST['db_name'] ?? '' ); $db_user = sanitize_text_field( $_POST['db_user'] ?? '' ); $password = sanitize_text_field( $_POST['password'] ?? '' ); $codeing = sanitize_text_field( $_POST['codeing'] ?? 'utf8mb4' ); $api = $this->api( $server_id ); wp_send_json( $api->add_database( $db_name, $db_user, $password, $codeing ) ); } public function ajax_wooaapanel_admin_db_delete(): void { $this->verify_admin(); $server_id = absint( $_POST['server_id'] ?? 0 ); $db_name = sanitize_text_field( $_POST['db_name'] ?? '' ); $api = $this->api( $server_id ); wp_send_json( $api->delete_database( $db_name ) ); } public function ajax_wooaapanel_admin_db_backup(): void { $this->verify_admin(); $server_id = absint( $_POST['server_id'] ?? 0 ); $db_name = sanitize_text_field( $_POST['db_name'] ?? '' ); $api = $this->api( $server_id ); wp_send_json( $api->backup_database( $db_name ) ); } public function ajax_wooaapanel_admin_db_backups(): void { $this->verify_admin(); $server_id = absint( $_POST['server_id'] ?? 0 ); $db_name = sanitize_text_field( $_POST['db_name'] ?? '' ); $api = $this->api( $server_id ); wp_send_json( $api->get_db_backups( $db_name ) ); } public function ajax_wooaapanel_admin_db_backup_delete(): void { $this->verify_admin(); $server_id = absint( $_POST['server_id'] ?? 0 ); $backup_id = absint( $_POST['backup_id'] ?? 0 ); $db_name = sanitize_text_field( $_POST['db_name'] ?? '' ); $api = $this->api( $server_id ); wp_send_json( $api->delete_db_backup( $backup_id, $db_name ) ); } public function ajax_wooaapanel_admin_db_optimize(): void { $this->verify_admin(); $server_id = absint( $_POST['server_id'] ?? 0 ); $db_name = sanitize_text_field( $_POST['db_name'] ?? '' ); $api = $this->api( $server_id ); wp_send_json( $api->optimize_table( $db_name ) ); } public function ajax_wooaapanel_admin_db_repair(): void { $this->verify_admin(); $server_id = absint( $_POST['server_id'] ?? 0 ); $db_name = sanitize_text_field( $_POST['db_name'] ?? '' ); $api = $this->api( $server_id ); wp_send_json( $api->repair_table( $db_name ) ); } public function ajax_wooaapanel_admin_db_access_get(): void { $this->verify_admin(); $server_id = absint( $_POST['server_id'] ?? 0 ); $db_name = sanitize_text_field( $_POST['db_name'] ?? '' ); $api = $this->api( $server_id ); wp_send_json( $api->get_db_access( $db_name ) ); } public function ajax_wooaapanel_admin_db_access_set(): void { $this->verify_admin(); $server_id = absint( $_POST['server_id'] ?? 0 ); $db_name = sanitize_text_field( $_POST['db_name'] ?? '' ); $access = sanitize_text_field( $_POST['access'] ?? '%' ); $api = $this->api( $server_id ); wp_send_json( $api->set_db_access( $db_name, $access ) ); } public function ajax_wooaapanel_admin_db_password(): void { $this->verify_admin(); $server_id = absint( $_POST['server_id'] ?? 0 ); $db_name = sanitize_text_field( $_POST['db_name'] ?? '' ); $db_user = sanitize_text_field( $_POST['db_user'] ?? '' ); $password = sanitize_text_field( $_POST['password'] ?? '' ); $api = $this->api( $server_id ); wp_send_json( $api->reset_db_password( $db_name, $db_user, $password ) ); } public function ajax_wooaapanel_admin_db_recycle(): void { $this->verify_admin(); $server_id = absint( $_POST['server_id'] ?? 0 ); $api = $this->api( $server_id ); wp_send_json( $api->get_recycle_bin() ); } public function ajax_wooaapanel_admin_db_restore(): void { $this->verify_admin(); $server_id = absint( $_POST['server_id'] ?? 0 ); $path = sanitize_text_field( $_POST['path'] ?? '' ); $api = $this->api( $server_id ); wp_send_json( $api->restore_from_recycle( $path ) ); } public function ajax_wooaapanel_admin_db_sync(): void { $this->verify_admin(); $server_id = absint( $_POST['server_id'] ?? 0 ); $api = $this->api( $server_id ); wp_send_json( $api->sync_to_databases() ); } public function ajax_wooaapanel_admin_db_quota(): void { $this->verify_admin(); $server_id = absint( $_POST['server_id'] ?? 0 ); $db_name = sanitize_text_field( $_POST['db_name'] ?? '' ); $quota_mb = absint( $_POST['quota_mb'] ?? 0 ); $api = $this->api( $server_id ); wp_send_json( $api->modify_db_quota( $db_name, $quota_mb ) ); } // ═════════════════════════════════════════════════════════════════════════ // AJAX: WC Product server linking // ═════════════════════════════════════════════════════════════════════════ public function ajax_wooaapanel_products_list(): void { $this->verify_admin(); $products = wc_get_products( [ 'limit' => 200, 'status' => 'publish' ] ); $servers = $this->get_all_servers(); $rows = []; foreach ( $products as $product ) { $rows[] = [ 'id' => $product->get_id(), 'name' => $product->get_name(), 'server_id' => (int) get_post_meta( $product->get_id(), '_wooaapanel_server_id', true ), ]; } wp_send_json_success( [ 'products' => $rows, 'servers' => $servers, ] ); } public function ajax_wooaapanel_product_server_save(): void { $this->verify_admin(); $product_id = absint( $_POST['product_id'] ?? 0 ); $server_id = absint( $_POST['server_id'] ?? 0 ); update_post_meta( $product_id, '_wooaapanel_server_id', $server_id ); wp_send_json_success(); } // ── Internal helpers ────────────────────────────────────────────────── private function get_all_servers(): array { global $wpdb; return $wpdb->get_results( "SELECT id, name FROM {$wpdb->prefix}wooaapanel_servers WHERE active = 1 ORDER BY name" ); } }