export_csv(); return; } include PEPTIDE_NEWS_PLUGIN_DIR . 'admin/partials/dashboard.php'; } /** * Stream a CSV export of click analytics data. * * Respects date range filters from GET parameters. * Defaults to last 30 days if not specified. * * @return void */ private function export_csv(): void { if ( ! current_user_can( 'manage_options' ) ) { wp_die( esc_html__( 'Unauthorized.', 'peptide-news' ) ); } $raw_start = isset( $_GET['start_date'] ) ? sanitize_text_field( wp_unslash( $_GET['start_date'] ) ) : ''; $raw_end = isset( $_GET['end_date'] ) ? sanitize_text_field( wp_unslash( $_GET['end_date'] ) ) : ''; $start_date = preg_match( '/^\d{4}-\d{2}-\d{2}$/', $raw_start ) ? $raw_start : gmdate( 'Y-m-d', strtotime( '-30 days' ) ); $end_date = preg_match( '/^\d{4}-\d{2}-\d{2}$/', $raw_end ) ? $raw_end : gmdate( 'Y-m-d' ); $data = Peptide_News_Analytics::export_clicks_csv( $start_date, $end_date ); $filename = 'peptide-news-clicks-' . $start_date . '-to-' . $end_date . '.csv'; header( 'Content-Type: text/csv; charset=utf-8' ); header( 'Content-Disposition: attachment; filename="' . $filename . '"' ); header( 'Pragma: no-cache' ); header( 'Expires: 0' ); $output = fopen( 'php://output', 'w' ); if ( ! empty( $data ) ) { fputcsv( $output, array_keys( $data[0] ) ); foreach ( $data as $row ) { fputcsv( $output, $row ); } } else { fputcsv( $output, array( 'No data for selected period' ) ); } fclose( $output ); exit; } /** * Render the articles management page. * * @return void */ public function render_articles_page(): void { if ( ! current_user_can( 'manage_options' ) ) { return; } include PEPTIDE_NEWS_PLUGIN_DIR . 'admin/partials/articles-list.php'; } /** * Render the LLM cost tracking dashboard page. * * Shows monthly budget status, daily cost chart, per-model breakdown, * and recent API call log. Data is loaded via AJAX for responsiveness. * * @since 2.4.0 * @return void */ public function render_cost_dashboard_page(): void { if ( ! current_user_can( 'manage_options' ) ) { return; } include PEPTIDE_NEWS_PLUGIN_DIR . 'admin/partials/cost-dashboard.php'; } }