query( $wpdb->prepare( "UPDATE {$wpdb->prefix}bosp_events SET report_count = report_count + 1 WHERE id = %d", $event_id ) ); wp_send_json_success(); } endif; // ============================================================ // 3. CANONICAL SUBCATEGORY MAP // Used by filter panel and normalize.py. // ============================================================ if ( ! function_exists( 'bosp_subcategory_map' ) ) : function bosp_subcategory_map() { return array( 'Music' => array( 'Axé', 'Blues', 'Bossa Nova', 'Choro', 'Classical', 'Electronic / DJ Set', 'Forró', 'Funk', 'Gospel', 'Hip-Hop / Rap', 'Jazz', 'MPB', 'Metal', 'Opera', 'Pagode', 'Punk / Rock', 'Reggae', 'Samba', 'Sertanejo', 'World Music', 'Other' ), 'Arts & Culture' => array( 'Art Exhibition', 'Craft Fair', 'Cultural Festival', 'Fashion Show', 'Film Screening', 'Gallery Opening', 'Heritage / History', 'Installation Art', 'Photography', 'Street Art', 'Other' ), 'Sports' => array( 'Basketball', 'Boxing / MMA', 'Cycling', 'Esports', 'Football (Soccer)', 'Futsal', 'Motor Racing', 'Running / Marathon', 'Swimming', 'Tennis', 'Volleyball', 'Other' ), 'Food & Drink' => array( 'Bar Night', 'Beer Festival', 'Cocktail Event', 'Coffee', 'Cooking Class', 'Food Fair', 'Food Truck', 'Restaurant Week', 'Wine Tasting', 'Other' ), 'Film & Cinema' => array( 'Documentary', 'Feature Film', 'Film Festival', 'Open-Air Cinema', 'Short Films', 'Other' ), 'Theater & Performance' => array( 'Circus', 'Comedy Show', 'Drama', 'Improv', 'Musical', 'Opera', 'Puppet Show', 'Stand-Up', 'Other' ), 'Dance' => array( 'Ballroom', 'Ballet', 'Baile Funk', 'Contemporary', 'Forró', 'Hip-Hop', 'Samba', 'Salsa / Zouk', 'Street Dance', 'Other' ), 'Comedy' => array( 'Improv', 'Open Mic', 'Stand-Up', 'Sketch', 'Other' ), 'Literature & Books' => array( 'Book Club', 'Book Fair', 'Book Launch', 'Poetry', 'Storytelling', 'Writing Workshop', 'Other' ), 'Family & Kids' => array( 'Children\'s Theater', 'Educational', 'Outdoor Play', 'Storytelling', 'Workshop', 'Other' ), 'Community & Social' => array( 'Block Party', 'Charity Event', 'Feira de Bairro', 'Meetup', 'Networking', 'Religious Gathering', 'Volunteer', 'Other' ), 'Health & Wellness' => array( 'Meditation', 'Mental Health', 'Nutrition', 'Pilates', 'Running Group', 'Wellness Fair', 'Yoga', 'Other' ), 'Education & Workshops' => array( 'Conference', 'Language Class', 'Lecture', 'Professional Development', 'Seminar', 'Skills Workshop', 'Other' ), 'Nightlife' => array( 'Bar Crawl', 'Club Night', 'Happy Hour', 'Karaoke', 'Late Night', 'Other' ), 'Outdoor & Nature' => array( 'Cycling', 'Hiking', 'Park Event', 'Picnic', 'Running', 'Street Fair', 'Other' ), 'Religion & Spirituality' => array( 'Buddhist', 'Catholic Mass', 'Candomblé', 'Evangelical', 'Jewish', 'Muslim', 'Spiritist', 'Umbanda', 'Other' ), 'Fashion' => array( 'Fashion Show', 'Pop-Up Shop', 'Sample Sale', 'Styling Workshop', 'Other' ), 'Technology' => array( 'Hackathon', 'Meetup', 'Product Launch', 'Startup Event', 'Tech Talk', 'Other' ), 'Other' => array( 'Other' ), ); } endif; // ============================================================ // 4. CORE PAGE BUILDER — shared by all three language files // ============================================================ if ( ! function_exists( 'bosp_build_events_page' ) ) : function bosp_build_events_page( $lang ) { global $wpdb; $table = $wpdb->prefix . 'bosp_events'; $today = gmdate( 'Y-m-d' ); // ---- UI STRINGS PER LANGUAGE ---- $strings = array( 'en' => array( 'search_placeholder' => 'Search events...', 'search_btn' => 'Search', 'creator_text' => 'Are you an event creator? ', 'creator_link' => 'Click here to add your event', 'filters_btn' => '⚙ Filters', 'category_label' => 'Category', 'date_label' => 'Date Range', 'date_from' => 'From', 'date_to' => 'To', 'time_label' => 'Time Range', 'time_from' => 'From', 'time_to' => 'To', 'price_label' => 'Price', 'price_all' => 'All events', 'price_free' => 'Free only', 'price_25' => 'Under R$25', 'community_label' => 'Community / Culture', 'access_label' => 'Accessibility', 'apply_filters' => 'Apply', 'clear_filters' => 'Clear All', 'pinned_label' => 'Featured', 'free_label' => 'Free', 'report_link' => 'Report / Ghost event', 'report_thanks' => 'Reported. Thanks.', 'no_events' => 'No events found.', 'lang_label' => 'Also in:', 'add_event_label' => 'ADD YOUR EVENT', 'filter_label' => 'SEARCH EVENTS BY FILTERS', 'search_label' => 'SEARCH EVENTS BY NAME', 'other_langs' => array( 'pt' => array( 'label' => 'Português', 'url' => '/sao-paulo-events/' ), 'es' => array( 'label' => 'Español', 'url' => '/eventos-de-sao-paulo-en-espanol/' ), ), ), 'pt' => array( 'search_placeholder' => 'Buscar eventos...', 'search_btn' => 'Buscar', 'creator_text' => 'Você organiza eventos? ', 'creator_link' => 'Clique aqui para adicionar seu evento', 'filters_btn' => '⚙ Filtros', 'category_label' => 'Categoria', 'date_label' => 'Período', 'date_from' => 'De', 'date_to' => 'Até', 'time_label' => 'Horário', 'time_from' => 'De', 'time_to' => 'Até', 'price_label' => 'Preço', 'price_all' => 'Todos os eventos', 'price_free' => 'Somente gratuitos', 'price_25' => 'Até R$25', 'community_label' => 'Comunidade / Cultura', 'access_label' => 'Acessibilidade', 'apply_filters' => 'Aplicar', 'clear_filters' => 'Limpar Tudo', 'pinned_label' => 'Destaque', 'free_label' => 'Gratuito', 'report_link' => 'Reportar / Evento fantasma', 'report_thanks' => 'Reportado. Obrigado.', 'no_events' => 'Nenhum evento encontrado.', 'lang_label' => 'Também em:', 'add_event_label' => 'ADICIONE SEU EVENTO', 'filter_label' => 'BUSCAR POR FILTROS', 'search_label' => 'BUSCAR POR NOME', 'other_langs' => array( 'en' => array( 'label' => 'English', 'url' => '/sao-paulo-events-in-english/' ), 'es' => array( 'label' => 'Español', 'url' => '/eventos-de-sao-paulo-en-espanol/' ), ), ), 'es' => array( 'search_placeholder' => 'Buscar eventos...', 'search_btn' => 'Buscar', 'creator_text' => '¿Organizas eventos? ', 'creator_link' => 'Haz clic aquí para agregar tu evento', 'filters_btn' => '⚙ Filtros', 'category_label' => 'Categoría', 'date_label' => 'Rango de fechas', 'date_from' => 'Desde', 'date_to' => 'Hasta', 'time_label' => 'Horario', 'time_from' => 'Desde', 'time_to' => 'Hasta', 'price_label' => 'Precio', 'price_all' => 'Todos los eventos', 'price_free' => 'Solo gratuitos', 'price_25' => 'Menos de R$25', 'community_label' => 'Comunidad / Cultura', 'access_label' => 'Accesibilidad', 'apply_filters' => 'Aplicar', 'clear_filters' => 'Limpiar Todo', 'pinned_label' => 'Destacado', 'free_label' => 'Gratis', 'report_link' => 'Reportar / Evento fantasma', 'report_thanks' => 'Reportado. Gracias.', 'no_events' => 'No se encontraron eventos.', 'lang_label' => 'También en:', 'add_event_label' => 'AGREGA TU EVENTO', 'filter_label' => 'BUSCAR POR FILTROS', 'search_label' => 'BUSCAR POR NOMBRE', 'other_langs' => array( 'en' => array( 'label' => 'English', 'url' => '/sao-paulo-events-in-english/' ), 'pt' => array( 'label' => 'Português', 'url' => '/sao-paulo-events/' ), ), ), ); $s = $strings[ $lang ] ?? $strings['en']; $name_col = 'name_' . $lang; $slug_col = 'slug_' . $lang; $desc_col = 'description_' . $lang; // ---- FETCH ADMIN-PINNED EVENTS ---- $pinned = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $table WHERE is_admin_posted = 1 AND is_banned = 0 AND event_date >= %s ORDER BY event_date ASC, event_time ASC", $today ) ); // ---- FETCH ALL UPCOMING EVENTS (chronological; admin first within slot) ---- $all_events = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $table WHERE is_banned = 0 AND event_date >= %s ORDER BY event_date ASC, is_admin_posted DESC, event_time ASC", $today ) ); // ---- FILTER OPTION LABELS ---- $form_strings = function_exists( 'bosp_form_strings' ) ? bosp_form_strings( $lang ) : array(); $en_strings = function_exists( 'bosp_form_strings' ) ? bosp_form_strings( 'en' ) : array(); $community_keys = array( 'comm_420','comm_africano','comm_afrobrazilian','comm_argentine','comm_armenian', 'comm_bolivian','comm_buddhist','comm_chilean','comm_chinese','comm_christian', 'comm_french','comm_german','comm_greek','comm_gringo','comm_haitian', 'comm_hindu','comm_indigenous','comm_italian','comm_japanese','comm_jewish', 'comm_korean','comm_lebanese','comm_lgbt','comm_mens','comm_muslim', 'comm_nordestino','comm_other','comm_peruvian','comm_petfriendly', 'comm_portuguese','comm_spanish','comm_students','comm_syrian','comm_trans', 'comm_women', ); $accessibility_keys = array( 'acc_18plus','acc_family','acc_neuro','acc_other','acc_senior','acc_wheelchair', ); $community_options = array(); $accessibility_options = array(); foreach ( $community_keys as $key ) { $community_options[] = array( 'value' => $en_strings[ $key ] ?? $key, 'label' => $form_strings[ $key ] ?? $en_strings[ $key ] ?? $key, ); } foreach ( $accessibility_keys as $key ) { $accessibility_options[] = array( 'value' => $en_strings[ $key ] ?? $key, 'label' => $form_strings[ $key ] ?? $en_strings[ $key ] ?? $key, ); } $subcategory_map = bosp_subcategory_map(); $report_nonce = wp_create_nonce( 'bosp_report_event' ); $ajax_url = admin_url( 'admin-ajax.php' ); $promo_banner_url = 'https://bestofsaopaulo.blog/wp-content/uploads/2026/03/Sao-Paulo-Events-FINAL-FLAT-PNG.png'; $promo_banner_href = 'https://brasilianart.com'; ob_start(); ?>
| |

event_date ?? ''; if ( $event_date && $event_date !== $current_date ) { $current_date = $event_date; $date_display = date_i18n( 'l, F j', strtotime( $event_date ) ); echo '
' . esc_html( $date_display ) . '
'; } echo bosp_render_event_card( $event, $lang, $s, $report_nonce, $ajax_url ); $card_count++; if ( $card_count % 7 === 0 ) { echo bosp_render_promo_card( $promo_banner_url, $promo_banner_href ); } endforeach; ?>
$name_col ?: $event->name_en ?: ''; $slug = $event->$slug_col ?: $event->slug_en ?: ''; $description = $event->$desc_col ?: $event->description_en ?: ''; $venue = $event->venue ?: ''; $neighborhood = $event->neighborhood ?: ''; $price = isset( $event->price ) ? (float) $event->price : null; $price_color = $event->price_color ?: 'green'; $event_time = $event->event_time ?: ''; $category = $event->category ?: ''; $subcategory = $event->subcategory ?: ''; $partner_discount = $event->partner_discount ?: ''; $event_id = (int) $event->id; $event_url = $slug ? home_url( '/event/' . $slug . '/' ) : '#'; // Price display if ( $price === null || $price === 0.0 ) { $price_display = $s['free_label']; $price_color = 'green'; } else { $price_display = 'R$' . number_format( $price, 2, ',', '.' ); } // Time display — skip midnight default $time_display = ''; if ( $event_time && $event_time !== '00:00:00' ) { $time_display = date( 'g:i A', strtotime( $event_time ) ); } // Description snippet — 20 words $desc_snippet = $description ? wp_trim_words( wp_strip_all_tags( $description ), 20, '...' ) : ''; // Meta line parts $meta_parts = array_filter( array( $venue, $neighborhood, $time_display ) ); ob_start(); ?>

★
BrasilianArt.com