sub( new DateInterval( 'P17Y' ) );
$born = new DateTimeImmutable(
sprintf( '%04d-%02d-%02d', $parsed['year'], $parsed['month'], $parsed['day'] ),
$timezone
);
// Positive when older than 17; negative when younger. Same framing as the original plugin.
return (int) $born->diff( $base )->format( '%r%a' );
}
/**
* Render year / month / day select controls.
*
* @param string|null $birthday Stored birth date or null for default (today − 17 years).
* @return string HTML (escaped).
*/
public static function render_selects( ?string $birthday ): string {
$timezone = wp_timezone();
$default = ( new DateTimeImmutable( 'today', $timezone ) )->sub( new DateInterval( 'P17Y' ) );
$parsed = null !== $birthday ? self::parse( $birthday ) : null;
$year = $parsed['year'] ?? (int) $default->format( 'Y' );
$month = $parsed['month'] ?? (int) $default->format( 'n' );
$day = $parsed['day'] ?? (int) $default->format( 'j' );
$current_year = (int) ( new DateTimeImmutable( 'now', $timezone ) )->format( 'Y' );
$min_year = $current_year - 100;
$year_html = '';
$month_html = '';
$day_html = '';
return $year_html . ' - ' . $month_html . ' - ' . $day_html;
}
/**
* Parse a Y-n-j (or similar) date string into components.
*
* @param string $value Raw date string.
* @return array{year:int,month:int,day:int}|null
*/
private static function parse( string $value ): ?array {
if ( ! preg_match( '/^(\d{4})-(\d{1,2})-(\d{1,2})$/', $value, $matches ) ) {
return null;
}
$year = (int) $matches[1];
$month = (int) $matches[2];
$day = (int) $matches[3];
if ( ! checkdate( $month, $day, $year ) ) {
return null;
}
return array(
'year' => $year,
'month' => $month,
'day' => $day,
);
}
}