{\rtf1\ansi\ansicpg1252\cocoartf2867 \cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fswiss\fcharset0 Helvetica;} {\colortbl;\red255\green255\blue255;} {\*\expandedcolortbl;;} \paperw11900\paperh16840\margl1440\margr1440\vieww11520\viewh8400\viewkind0 \pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural\partightenfactor0 \f0\fs24 \cf0 prefix . self::TABLE_VOTES;\ $charset = $wpdb->get_charset_collate();\ \ require_once ABSPATH . 'wp-admin/includes/upgrade.php';\ \ $sql = "CREATE TABLE $table (\ id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,\ poll_id VARCHAR(64) NOT NULL,\ choice TINYINT UNSIGNED NOT NULL,\ voter_hash CHAR(64) NOT NULL,\ created_at DATETIME NOT NULL,\ PRIMARY KEY (id),\ KEY poll_id_idx (poll_id),\ KEY poll_choice_idx (poll_id, choice),\ UNIQUE KEY poll_voter_unique (poll_id, voter_hash)\ ) $charset;";\ \ dbDelta($sql);\ \}\ \ public static function enqueue_assets() \{\ // Only load on pages where shortcode exists (basic optimisation)\ if (!is_singular()) return;\ global $post;\ if (!$post || stripos($post->post_content, '[ays_poll') === false) return;\ \ $handle = 'litfl-ecg-polls';\ wp_register_script(\ $handle,\ plugins_url('litfl-ecg-polls.js', __FILE__),\ [],\ '1.0.0',\ true\ );\ \ wp_localize_script($handle, 'LITFLPoll', [\ 'ajaxUrl' => admin_url('admin-ajax.php'),\ 'nonce' => wp_create_nonce(self::NONCE_ACTION),\ ]);\ \ wp_enqueue_script($handle);\ \ // Minimal CSS to mimic your old \'93button list\'94 style\ $css = "\ .litfl-poll \{ border: 2px solid #1e5bd7; border-radius: 10px; padding: 18px; margin: 18px 0; position: relative; background: #fff; \}\ .litfl-poll h5 \{ margin: 0 0 14px 0; font-size: 28px; line-height: 1.15; color: #1e5bd7; font-weight: 700; \}\ .litfl-poll .litfl-option \{ display:block; width:100%; text-align:left; border: 2px solid #2b2b2b; padding: 18px 16px; margin: 12px 0; background: #efefef; font-size: 28px; cursor:pointer; \}\ .litfl-poll .litfl-option:hover \{ filter: brightness(0.98); \}\ .litfl-poll .litfl-meta \{ margin-top: 14px; font-size: 16px; color:#333; \}\ .litfl-poll .litfl-counts \{ margin-top: 10px; font-size: 18px; color:#111; \}\ .litfl-poll .litfl-badge \{ position:absolute; right: 16px; bottom: 16px; background:#1e5bd7; color:#fff; padding: 10px 14px; border-radius: 8px; font-size: 28px; font-weight: 700; \}\ .litfl-poll .litfl-msg \{ margin-top: 10px; font-size: 16px; \}\ ";\ wp_register_style('litfl-ecg-polls-style', false);\ wp_enqueue_style('litfl-ecg-polls-style');\ wp_add_inline_style('litfl-ecg-polls-style', $css);\ \}\ \ public static function shortcode_ays_poll($atts) \{\ $atts = shortcode_atts([\ 'id' => '',\ 'question' => 'Would you activate your cath lab/STEMI protocol?',\ 'a' => 'Yes',\ 'b' => 'No',\ 'c' => 'Not sure. Review in Emergency.',\ ], $atts);\ \ $poll_id = sanitize_text_field($atts['id']);\ if ($poll_id === '') \{\ // Fallback: tie to current post ID if someone forgets the id=\ $poll_id = get_the_ID();\ \}\ \ $already = self::has_voted($poll_id);\ \ ob_start(); ?>\
\
\ \ \ \ \ \
\
Loading results\'85
\
\'97
\
\ prefix . self::TABLE_VOTES;\ \ $rows = $wpdb->get_results(\ $wpdb->prepare(\ "SELECT choice, COUNT(*) as cnt FROM $table WHERE poll_id = %s GROUP BY choice",\ $poll_id\ ),\ ARRAY_A\ );\ \ $counts = [1 => 0, 2 => 0, 3 => 0];\ $total = 0;\ \ foreach ($rows as $r) \{\ $c = (int)$r['choice'];\ $n = (int)$r['cnt'];\ if (isset($counts[$c])) \{\ $counts[$c] = $n;\ $total += $n;\ \}\ \}\ \ return [$counts, $total];\ \}\ \ public static function ajax_results() \{\ $poll_id = sanitize_text_field($_GET['poll_id'] ?? '');\ if ($poll_id === '') wp_send_json_error(['message' => 'Missing poll_id']);\ \ [$counts, $total] = self::get_counts($poll_id);\ wp_send_json_success(['counts' => $counts, 'total' => $total, 'already' => self::has_voted($poll_id)]);\ \}\ \ public static function ajax_vote() \{\ check_ajax_referer(self::NONCE_ACTION, 'nonce');\ \ $poll_id = sanitize_text_field($_POST['poll_id'] ?? '');\ $choice = (int)($_POST['choice'] ?? 0);\ \ if ($poll_id === '' || !in_array($choice, [1,2,3], true)) \{\ wp_send_json_error(['message' => 'Invalid vote']);\ \}\ \ // If already voted (cookie), just return current results\ if (self::has_voted($poll_id)) \{\ [$counts, $total] = self::get_counts($poll_id);\ wp_send_json_success(['counts' => $counts, 'total' => $total, 'already' => true]);\ \}\ \ global $wpdb;\ $table = $wpdb->prefix . self::TABLE_VOTES;\ \ $inserted = $wpdb->insert(\ $table,\ [\ 'poll_id' => $poll_id,\ 'choice' => $choice,\ 'voter_hash' => self::voter_hash(),\ 'created_at' => current_time('mysql'),\ ],\ ['%s','%d','%s','%s']\ );\ \ // If unique constraint blocks duplicate voter_hash, treat as already voted\ if ($inserted === false) \{\ [$counts, $total] = self::get_counts($poll_id);\ wp_send_json_success(['counts' => $counts, 'total' => $total, 'already' => true]);\ \}\ \ // Set cookie for ~1 year\ setcookie(self::COOKIE_PREFIX . $poll_id, '1', time() + YEAR_IN_SECONDS, COOKIEPATH ?: '/', COOKIE_DOMAIN ?: '', is_ssl(), true);\ \ [$counts, $total] = self::get_counts($poll_id);\ wp_send_json_success(['counts' => $counts, 'total' => $total, 'already' => true]);\ \}\ \}\ \ LITFL_ECG_Polls::init();\ }