/* ═══════════════════════════════════════════════════════════════ OUT-OF-CATALOG ARRIVALS (the /new/ surfaces only) OOC titles are auto-ingested and not yet hand-reviewed, so they stay out of fv_build_index() and off every browse page — that index is what /all/, the archives and the homepage rows all read, and every pick there is curator-vouched. "New on" is a different claim: it says a title landed on a service, not that we vouch for it. So the /new/ pages and the homepage's New shelf pull OOC arrivals from here and merge them in, and nothing else sees them. Entries are shaped like fv_build_index() entries so the callers need no special case beyond the merge. Cached for an hour; bump the key to force a rebuild. ═══════════════════════════════════════════════════════════════ */ function agmtw_ooc_arrivals( $geo = 'US' ) { static $memo = []; $map = [ 'US' => 'usa', 'CA' => 'canada', 'GB' => 'uk' ]; if ( ! isset( $map[ $geo ] ) ) $geo = 'US'; if ( isset( $memo[ $geo ] ) ) return $memo[ $geo ]; $key = 'agmtw_ooc_arrivals_v1_' . strtolower( $geo ); $cached = get_transient( $key ); if ( is_array( $cached ) ) return $memo[ $geo ] = $cached; global $wpdb; $prefix = $map[ $geo ]; $cutoff = time() - ( 90 * DAY_IN_SECONDS ); // 1) Arrival stamps first: only OOC titles that actually landed somewhere // recently are worth loading at all. $rows = $wpdb->get_results( $wpdb->prepare( "SELECT m.post_id, m.meta_key, m.meta_value FROM {$wpdb->postmeta} m JOIN {$wpdb->posts} p ON p.ID = m.post_id WHERE p.post_status = 'outofcatalog' AND p.post_type IN ('post','shows') AND m.meta_key LIKE %s AND m.meta_value REGEXP '^[0-9]+$' AND CAST( m.meta_value AS UNSIGNED ) >= %d", $prefix . '-%-date', $cutoff ) ); if ( ! $rows ) { set_transient( $key, [], HOUR_IN_SECONDS ); return $memo[ $geo ] = []; } $plen = strlen( $prefix . '-' ); $slen = strlen( '-date' ); $arrivals = []; foreach ( $rows as $r ) { $streamer = substr( $r->meta_key, $plen, -$slen ); if ( $streamer === '' || $streamer === 'arrival' ) continue; $pid = (int) $r->post_id; $ts = (int) $r->meta_value; if ( ! isset( $arrivals[ $pid ][ $streamer ] ) || $arrivals[ $pid ][ $streamer ] < $ts ) { $arrivals[ $pid ][ $streamer ] = $ts; } } $ids = array_keys( $arrivals ); $ids_csv = implode( ',', array_map( 'intval', $ids ) ); // 2) Titles + type, 3) the taxonomies the /new/ table prints, 4) the // streamer tags an arrival has to be backed by. $meta_rows = $wpdb->get_results( "SELECT ID, post_type, post_title FROM {$wpdb->posts} WHERE ID IN ($ids_csv)" ); $tax_rows = $wpdb->get_results( " SELECT tr.object_id, tt.taxonomy, t.slug FROM {$wpdb->term_relationships} tr JOIN {$wpdb->term_taxonomy} tt ON tr.term_taxonomy_id = tt.term_taxonomy_id JOIN {$wpdb->terms} t ON tt.term_id = t.term_id WHERE tr.object_id IN ($ids_csv) AND tt.taxonomy IN ('category','language','released','post_tag') " ); $sr_rows = $wpdb->get_results( "SELECT post_id, meta_value FROM {$wpdb->postmeta} WHERE post_id IN ($ids_csv) AND meta_key = 'staffrating'" ); $genres = $langs = $years = $streamers = []; foreach ( $tax_rows as $t ) { $pid = (int) $t->object_id; if ( $t->taxonomy === 'category' ) $genres[ $pid ][] = $t->slug; elseif ( $t->taxonomy === 'language' ) $langs[ $pid ][] = $t->slug; elseif ( $t->taxonomy === 'released' ) $years[ $pid ][] = $t->slug; elseif ( strpos( $t->slug, $prefix . '-' ) === 0 ) { $streamers[ $pid ][ substr( $t->slug, $plen ) ] = true; } } $sr = []; foreach ( $sr_rows as $r ) $sr[ (int) $r->post_id ] = (int) $r->meta_value; $out = []; foreach ( $meta_rows as $p ) { $pid = (int) $p->ID; // An arrival with no matching tag means the title has since dropped // off that service; same guard the main index applies. $arr = []; foreach ( ( $arrivals[ $pid ] ?? [] ) as $s => $ts ) { if ( isset( $streamers[ $pid ][ $s ] ) ) $arr[ $s ] = $ts; } if ( ! $arr ) continue; $out[] = [ 'id' => $pid, 'type' => $p->post_type, 'title' => html_entity_decode( $p->post_title, ENT_QUOTES, 'UTF-8' ), 'staffrating' => $sr[ $pid ] ?? 0, 'isPro' => false, 'isOOC' => true, 'streamers' => array_keys( $streamers[ $pid ] ?? [] ), 'genres' => $genres[ $pid ] ?? [], 'languages' => $langs[ $pid ] ?? [], 'released' => $years[ $pid ] ?? [], 'moods' => [], 'countries' => [], 'arrivals' => $arr, 'latestArrival' => max( $arr ), ]; } set_transient( $key, $out, HOUR_IN_SECONDS ); return $memo[ $geo ] = $out; }
With its celebration of Thai dances, excellent costumes, and two male theater actor leads, ManSuang seemed like it would be something akin to a Thai Farewell My Concubine, especially as it starts off with what could have been sex scene interrupted by a murder. The addition of the espionage storyline, as well as the dynamics between the Chinese and the mainland Thai, seemed like the film would be subtle social commentary through historical drama. However, the story feels haphazardly assembled, with characters acting contrary to their goals, and sadly, the film doesn’t showcase as much of Thai culture as we would like. Instead, the film spends more time establishing an overly complicated mystery that gets too hard to follow with its multiple plotlines. ManSuang has beautiful set design, costumes, and a handsome cast, but the writing wastes the potential the story had.
In a fight for their lives, two dancers infiltrate a high-profile social club and seek the help of a newfound ally to unmask traitors to Siam.
Siam, 1850. After being falsely accused of murder, theater actors Khem and Wan have a chance at an official pardon if they manage to infiltrate Man Suang, the mysterious Siamese entertainment club that secretly hosts various political negotiations during the end of King Rama III’s reign.
ManSuang’s premise is interesting, but the way the story flowed feels boring and overly complicated because it never establishes what’s emotionally at stake for the characters. The film also shies away from depicting the emotional side of the relationships between Khem, Wan, and Chatra, even in a platonic way. Because of this, every move they make feels random, even when the choices they make could mean the end of their lives.
Apo Nattawin Wattanagitiphat is so handsome, though…