/* ══════════════════════════════════════════════════════════════
4. AUTO-PROCESS QUICK FACTS ON SAVE
══════════════════════════════════════════════════════════════ */
function tcc_auto_parse_quick_facts( $post_id, $post, $update ) {
/* ── Guards ── */
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return;
if ( wp_is_post_revision( $post_id ) ) return;
if ( wp_is_post_autosave( $post_id ) ) return;
if ( ! in_array( $post->post_type, [ 'post', 'page' ], true ) ) return;
if ( ! current_user_can( 'edit_post', $post_id ) ) return;
$content = $post->post_content;
/* ── Heading keywords to look for ── */
$heading_pattern = 'Quick Facts|Profile|Wiki Facts|About';
/* ── Only proceed if one of the headings exists ── */
if ( ! preg_match( '/(' . $heading_pattern . ')/i', $content ) ) return;
/* ── Label map ── */
$label_map = [
'full name' => '_bio_full_name',
'real name' => '_bio_full_name',
'stage name' => '_bio_stage_name',
'nickname' => '_bio_stage_name',
'known as' => '_bio_stage_name',
'born' => '_bio_born',
'date of birth' => '_bio_born',
'dob' => '_bio_born',
'birth date' => '_bio_born',
'age' => '_bio_age',
'death' => '_bio_death',
'died' => '_bio_death',
'date of death' => '_bio_death',
'passed away' => '_bio_death',
'birthplace' => '_bio_birthplace',
'place of birth' => '_bio_birthplace',
'birth place' => '_bio_birthplace',
'hometown' => '_bio_birthplace',
'born in' => '_bio_birthplace',
'state of origin' => '_bio_state_origin',
'nationality' => '_bio_nationality',
'ethnicity' => '_bio_nationality',
'citizenship' => '_bio_nationality',
'occupation' => '_bio_occupation',
'profession' => '_bio_occupation',
'height' => '_bio_height',
'religion' => '_bio_religion',
'faith' => '_bio_religion',
'parents' => '_bio_parents',
'father' => '_bio_parents',
'mother' => '_bio_parents',
'parent' => '_bio_parents',
'siblings' => '_bio_siblings',
'sibling' => '_bio_siblings',
'spouse' => '_bio_spouse',
'husband' => '_bio_spouse',
'wife' => '_bio_spouse',
'married to' => '_bio_spouse',
'children' => '_bio_children',
'child' => '_bio_children',
'kids' => '_bio_children',
'relationship' => '_bio_relationship',
'relationship status' => '_bio_relationship',
'marital status' => '_bio_relationship',
'net worth' => '_bio_net_worth',
'worth' => '_bio_net_worth',
'wealth' => '_bio_net_worth',
'earnings' => '_bio_net_worth',
];
/* ── Values to skip ── */
$skip_values = [
'n/a', 'unknown', 'none', 'not available', 'nil',
'not married', 'not dating', 'no', '-', 'tbd', 'tba',
];
/* ── Extract lines from the facts block ── */
$lines = [];
$block_start = '';
$block_end = '';
/*
* Strategy 1 — Gutenberg block format
* Matches: ...
Quick Facts
...
* ... ... ...
*/
$gutenberg_pattern = '/.*?]*>(?:' . $heading_pattern . ').*?<\/h[23]>.*?\s*(.*?)/si';
if ( preg_match( $gutenberg_pattern, $content, $block_match, PREG_OFFSET_CAPTURE ) ) {
$full_block = $block_match[0][0];
$block_start = $block_match[0][0];
$list_html = $block_match[1][0];
if ( preg_match_all( '/]*>(.*?)<\/li>/si', $list_html, $li_matches ) ) {
$lines = array_map( 'wp_strip_all_tags', $li_matches[1] );
}
/*
* Strategy 2 — Classic HTML h2 + ul/li
*/
} elseif ( preg_match( '/]*>(?:' . $heading_pattern . ').*?<\/h2>(.*?)(?=]*>(.*?)<\/li>/si', $section, $li_matches ) ) {
$lines = array_map( 'wp_strip_all_tags', $li_matches[1] );
} else {
preg_match_all( '/[\*\-\•]\s*(.+)/u', wp_strip_all_tags( $section ), $bullet_matches );
$lines = $bullet_matches[1] ?? [];
}
/*
* Strategy 3 — Plain text / markdown bullet list
*/
} elseif ( preg_match( '/(?:' . $heading_pattern . ')\s*\n((?:[\*\-\•][^\n]+\n?)+)/i', $content, $section_match ) ) {
$block_start = $section_match[0];
preg_match_all( '/[\*\-\•]\s*(.+)/u', $section_match[1], $bullet_matches );
$lines = $bullet_matches[1] ?? [];
}
if ( empty( $lines ) ) return;
/* ── Parse lines into fields ── */
$fields = [];
foreach ( $lines as $line ) {
$line = trim( wp_strip_all_tags( $line ) );
$line = preg_replace( '/^[\*\-\•]\s*/', '', $line );
$line = trim( $line );
if ( ! preg_match( '/^([^:]+):\s*(.+)$/', $line, $match ) ) continue;
$raw_label = strtolower( trim( $match[1] ) );
$value = trim( $match[2] );
if ( empty( $value ) ) continue;
if ( in_array( strtolower( $value ), $skip_values, true ) ) continue;
/* Strip "years old" from age */
if ( strpos( $raw_label, 'age' ) !== false ) {
$value = trim( preg_replace( '/\s*years?\s*old/i', '', $value ) );
}
/* Strip trailing USD from net worth */
if ( strpos( $raw_label, 'worth' ) !== false || strpos( $raw_label, 'wealth' ) !== false ) {
$value = trim( preg_replace( '/\s*USD$/i', '', $value ) );
}
/* Longest pattern match wins */
$matched_key = null;
$matched_length = 0;
foreach ( $label_map as $pattern => $meta_key ) {
if ( strpos( $raw_label, $pattern ) !== false && strlen( $pattern ) > $matched_length ) {
$matched_key = $meta_key;
$matched_length = strlen( $pattern );
}
}
if ( ! $matched_key ) continue;
if ( isset( $fields[ $matched_key ] ) ) continue;
$fields[ $matched_key ] = sanitize_text_field( $value );
}
if ( empty( $fields ) ) return;
/* ── Save meta — never overwrite existing values ── */
foreach ( $fields as $meta_key => $value ) {
$existing = get_post_meta( $post_id, $meta_key, true );
if ( empty( $existing ) ) {
update_post_meta( $post_id, $meta_key, $value );
}
}
/* ── Strip the facts block from content ── */
$new_content = $content;
if ( ! empty( $block_start ) ) {
/* Remove the exact matched block */
$new_content = str_replace( $block_start, '', $new_content );
}
/* Fallback: remove any remaining Quick Facts / Profile h2 + list */
$new_content = preg_replace(
'/.*?]*>(?:' . $heading_pattern . ').*?<\/h[23]>.*?\s*.*?/si',
'',
$new_content
);
$new_content = preg_replace(
'/]*>(?:' . $heading_pattern . ').*?<\/h2>.*?(?=]*-->.*?/si', '', $new_content );
$new_content = preg_replace( '/(\s*<\/p>\s*)+/', '', $new_content );
$new_content = preg_replace( '/\n{3,}/', "\n\n", $new_content );
$new_content = trim( $new_content );
/* ── Insert [bio_infobox] at top if not already present ── */
if ( strpos( $new_content, '[bio_infobox]' ) === false ) {
$new_content = '[bio_infobox]' . "\n\n" . $new_content;
}
/* ── Update post content only if changed ── */
if ( $new_content !== $content ) {
remove_action( 'save_post', 'tcc_auto_parse_quick_facts', 20 );
wp_update_post([
'ID' => $post_id,
'post_content' => $new_content,
]);
add_action( 'save_post', 'tcc_auto_parse_quick_facts', 20, 3 );
}
}
add_action( 'save_post', 'tcc_auto_parse_quick_facts', 20, 3 );
Mark Goodson » Bio, Age, Net Worth, Family
Skip to the content
Home » Mark Goodson
July 1, 2022
Posted By
Abigail Anderson
Biography George Alexander Trebek OC (born July 22, 1940), addressed professionally as Alex Trebek, is a Canadian TV host and…