'PT35M13S',
'pB5YojrQOdc' => 'PT19S',
'6IyxaiHVjHM' => 'PT1M18S',
'EU4plNVcKz8' => 'PT4M3S',
'UMAMsKUs5es' => 'PT55M30S',
'HOdRMe15blo' => 'PT1M12S',
'n_DhhevtfJI' => 'PT22M8S',
'xqC_y4DRZM8' => 'PT49S',
'gEsYin5WQM8' => 'PT40M50S',
'4gVUoKWV9IU' => 'PT6M17S',
);
}
}
if ( ! function_exists( 'nmk_itemlist_extract_yt_id' ) ) {
function nmk_itemlist_extract_yt_id( $url ) {
if ( preg_match( '~(?:youtube.com/(?:embed/|watch?v=)|youtu.be/)([A-Za-z0-9_-]{11})~i', (string) $url, $m ) ) {
return $m[1];
}
return ";
}
}
if ( ! function_exists( 'nmk_itemlist_fix_json' ) ) {
function nmk_itemlist_fix_json( $html ) {
$dur_map = nmk_itemlist_yt_duration_map();
// Find all JSON-LD script blocks
$html = preg_replace_callback(
'/]*type=["']application/ld+json["'][^>]*>(.*?)/si',
function( $matches ) use ( $dur_map ) {
$json_str = $matches[1];
$raw = trim( $json_str );
// Only process if it contains VideoObject and ItemList or missing duration
if ( strpos( $raw, 'VideoObject' ) === false ) return $matches[0];
try {
$data = json_decode( $raw, true );
if ( json_last_error() !== JSON_ERROR_NONE ) return $matches[0];
$modified = false;
// Recursive fixer
$fixer = null;
$fixer = function( &$node ) use ( &$fixer, $dur_map, &$modified ) {
if ( ! is_array( $node ) ) return;
if ( isset( $node['@type'] ) && $node['@type'] === 'VideoObject' ) {
$has_duration = ! empty( $node['duration'] ) && preg_match( '/^PT/i', $node['duration'] );
if ( ! $has_duration ) {
// Try to find YT ID from various fields
$yt_id = ";
foreach ( array( 'contentUrl', ’embedUrl', 'url' ) as $field ) {
if ( ! empty( $node[ $field ] ) ) {
$yt_id = nmk_itemlist_extract_yt_id( $node[ $field ] );
if ( $yt_id ) break;
}
}
if ( $yt_id && isset( $dur_map[ $yt_id ] ) ) {
$node['duration'] = $dur_map[ $yt_id ];
$modified = true;
}
}
// Also fix uploadDate format
if ( ! empty( $node['uploadDate'] ) && ! preg_match( '/[T+Z]/', $node['uploadDate'] ) ) {
$tz = wp_timezone();
try {
$dt = new DateTime( $node['uploadDate'] . ' 00:00:00', $tz );
$node['uploadDate'] = $dt->format( 'c' );
$modified = true;
} catch ( Exception $e ) {}
}
if ( ! empty( $node['datePublished'] ) && empty( $node['uploadDate'] ) ) {
$node['uploadDate'] = $node['datePublished'];
$modified = true;
}
}
foreach ( $node as $key => &$val ) {
if ( is_array( $val ) ) $fixer( $val );
}
};
$fixer( $data );
if ( $modified ) {
$new_json = wp_json_encode( $data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT );
return str_replace( $matches[1], "n" . $new_json . "n", $matches[0] );
}
} catch ( Exception $e ) {}
return $matches[0];
},
$html
);
return $html;
}
}
// Hook into output buffer
if ( ! function_exists( 'nmk_itemlist_ob_start' ) ) {
function nmk_itemlist_ob_start() {
ob_start( 'nmk_itemlist_fix_json' );
}
}
add_action( 'template_redirect', 'nmk_itemlist_ob_start', 1 );