table = $wpdb->prefix . ‘Legal_Eagle_Weekly_picks’;
register_activation_hook(__FILE__, array($this, ‘activate’));
add_shortcode(‘Legal_Eagle_Weekly_picks’, array($this, ‘shortcode’));
add_action(‘init’, array($this, ‘handle_submission’));
add_action(‘admin_menu’, array($this, ‘admin_menu’));
}

public function activate(){
global $wpdb; $charset_collate = $wpdb->get_charset_collate();
$sql = “CREATE TABLE {$this->table} (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
user_id BIGINT UNSIGNED NOT NULL,
week VARCHAR(20) NOT NULL,
pick TEXT NOT NULL,
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (id),
UNIQUE KEY unique_user_week (user_id, week),
KEY week_idx (week)
) $charset_collate;”;
require_once ABSPATH . ‘wp-admin/includes/upgrade.php’;
dbDelta($sql);
}

private function current_user_allowed(){
if (!is_user_logged_in()) return false;
if (empty($this->allowed_identifiers)) return true; // if not configured yet, let anyone (for dev)
$user = wp_get_current_user();
$set = array_map(‘strtolower’, $this->allowed_identifiers);
return in_array(strtolower($user->user_login), $set, true) || in_array(strtolower($user->user_email), $set, true);
}

public function handle_submission(){
if (!isset($_POST[‘swp_nonce’]) || !wp_verify_nonce($_POST[‘swp_nonce’], ‘swp_submit’)) return;
if (!is_user_logged_in()) return;
if (!$this->current_user_allowed()) return;
if (!isset($_POST[‘swp_action’]) || $_POST[‘swp_action’] !== ‘submit_pick’) return;

$week = isset($_POST[‘swp_week’]) ? sanitize_text_field(wp_unslash($_POST[‘swp_week’])) : ”;
$pick = isset($_POST[‘swp_pick’]) ? wp_kses_post(wp_unslash($_POST[‘swp_pick’])) : ”;

if ($week === ” || $pick === ”){
wp_redirect(add_query_arg(‘swp_msg’, ‘missing’, wp_get_referer()));
exit;
}

global $wpdb; $user_id = get_current_user_id();
$data = array(‘user_id’ => $user_id, ‘week’ => $week, ‘pick’ => $pick);

// insert or update (unique on user_id+week)
$existing = $wpdb->get_var($wpdb->prepare(“SELECT id FROM {$this->table} WHERE user_id=%d AND week=%s”, $user_id, $week));
if ($existing){
$wpdb->update($this->table, $data, array(‘id’ => $existing));
$status = ‘updated’;
} else {
$wpdb->insert($this->table, $data);
$status = ‘saved’;
}
wp_redirect(add_query_arg(‘swp_msg’, $status, remove_query_arg(array(‘swp_msg’))));
exit;
}

public function shortcode($atts){
$a = shortcode_atts(array(
‘week’ => ”, // e.g., “2025-W01” or “Week 8”
), $atts, ‘Legal_Eagle_Weekly_picks’);

ob_start();
echo ‘

‘;
echo ‘

Surge Weekly Picks

‘;

if (!is_user_logged_in()){
echo ‘

You must be logged in to submit a pick.

‘;
echo ‘

‘;
return ob_get_clean();
}

if (!$this->current_user_allowed()){
echo ‘

Sorry, you are not on the list of participants for this contest.

‘;
echo ‘

‘;
return ob_get_clean();
}

$current_week = $a[‘week’] !== ” ? $a[‘week’] : $this->default_week_label();
$msg = isset($_GET[‘swp_msg’]) ? sanitize_text_field($_GET[‘swp_msg’]) : ”;
if ($msg){
$map = array(‘saved’ => ‘Pick saved!’, ‘updated’ => ‘Pick updated!’, ‘missing’ => ‘Please enter a week and a pick.’);
$notice = isset($map[$msg]) ? $map[$msg] : ”;
if ($notice) echo ‘

‘ . esc_html($notice) . ‘

‘;
}

// Submission form
echo ‘

‘;
echo ‘‘;
echo ‘‘;
wp_nonce_field(‘swp_submit’, ‘swp_nonce’);
echo ‘‘;
echo ‘‘;
echo ‘

‘;

// Show table of this week picks for all 12
echo ‘

This Week\’s Picks (‘ . esc_html($current_week) . ‘)

‘;
$this->render_table($current_week);

echo ‘

MVP build — unique per user per week. Editing replaces your existing pick for that week.

‘;
echo ‘

‘;
return ob_get_clean();
}

private function default_week_label(){
// ISO week like 2025-W44 by default
$dt = new DateTime(‘now’, wp_timezone());
$year = $dt->format(‘o’);
$week = $dt->format(‘W’);
return sprintf(‘%s-W%02d’, $year, $week);
}

private function render_table($week){
global $wpdb;
$rows = $wpdb->get_results($wpdb->prepare(“SELECT p.*, u.display_name
FROM {$this->table} p
JOIN {$wpdb->users} u ON u.ID = p.user_id
WHERE p.week = %s
ORDER BY u.display_name ASC”, $week));

echo ‘

‘;
echo ‘

‘;
echo ‘


. ‘


. ‘


. ‘


. ‘

‘;
echo ‘

‘;
if ($rows){
foreach ($rows as $r){
echo ‘


. ‘


. ‘


. ‘


. ‘

‘;
}
} else {
echo ‘

‘;
}
echo ‘

User Pick Updated
‘ . esc_html($r->display_name) . ‘ ‘ . wp_kses_post($r->pick) . ‘ ‘ . esc_html(date_i18n(get_option(‘date_format’) . ‘ ‘ . get_option(‘time_format’), strtotime($r->updated_at))) . ‘
No picks yet for this week.

‘;
}

public function admin_menu(){
add_menu_page(‘Surge Picks’, ‘Surge Picks’, ‘manage_options’, ‘surge-picks’, array($this, ‘admin_page’), ‘dashicons-chart-line’, 58);
}

public function admin_page(){
if (!current_user_can(‘manage_options’)) return;
echo ‘

Surge Weekly Picks

‘;
echo ‘

Export CSV for a given week.

‘;
echo ‘

‘;
echo ‘ ‘;
submit_button(‘Export CSV’, ‘secondary’, ‘swp_export_btn’, false);
echo ‘

‘;

if (isset($_POST[‘swp_export_btn’])){
$week = isset($_POST[‘swp_export_week’]) ? sanitize_text_field(wp_unslash($_POST[‘swp_export_week’])) : ”;
if ($week !== ”){
$this->export_csv($week);
}
}

echo ‘


Participants (12): Configure by editing $allowed_identifiers in the plugin for now. We\’ll add a settings UI next.

‘;
echo ‘

‘;
}

private function export_csv($week){
if (!current_user_can(‘manage_options’)) return;
global $wpdb;
$rows = $wpdb->get_results($wpdb->prepare(“SELECT u.display_name AS user, p.week, p.pick, p.updated_at
FROM {$this->table} p JOIN {$wpdb->users} u ON u.ID = p.user_id WHERE p.week=%s ORDER BY u.display_name ASC”, $week), ARRAY_A);
if (!$rows) {
echo ‘

No data for that week.

‘;
return;
}
$filename = ‘surge-picks-‘ . sanitize_title($week) . ‘-‘ . gmdate(‘Ymd-His’) . ‘.csv’;
header(‘Content-Type: text/csv; charset=utf-8’);
header(‘Content-Disposition: attachment; filename=’ . $filename);
$out = fopen(‘php://output’, ‘w’);
fputcsv($out, array(‘User’, ‘Week’, ‘Pick’, ‘Updated’));
foreach ($rows as $r) fputcsv($out, $r);
fclose($out);
exit;
}
}

Legal_Eagle_Weekly_Picks::instance();