Automattic\WooCommerce\Blocks\Domain\Services\CheckoutFieldTypes
DateFieldType::resolve_constraint
Resolves a date field min/max constraint to a YYYY-MM-DD date in the store's timezone.
Durations are resolved at read time, so they follow the current date rather than freezing into whatever markup a page cache stored.
We use DateInterval to resolve durations but it has 2 issues that we must solve here:
- Negative constraints are not supported with this version, so we must account for them ourselves.
- DateInterval has an inconsistent behavior compared to ISO 8601-2 in which adding a month to a date equals adding 31 days instead of a calendar month, resulting in P1M after Jan 31 giving you Mar 3 instead of Feb 28.
Метод класса: DateFieldType{}
Хуков нет.
Возвращает
string. The resolved date.
Использование
// private - только в коде основоного (родительского) класса $result = $this->resolve_constraint( $value, $reference ): string;
- $value(строка) (обязательный)
- The constraint, as validated and normalized at registration.
- $reference(DateTimeInterface|null)
- Date a duration is relative to.
По умолчанию:today in the store timezone
Код DateFieldType::resolve_constraint() DateFieldType::resolve constraint WC 11.2.2
private function resolve_constraint( string $value, $reference = null ): string {
if ( $this->is_absolute_date( $value ) ) {
return $value;
}
$sign = '-' === $value[0] ? -1 : 1;
$interval = self::parse_duration( ltrim( $value, '-' ) );
$today = new \DateTimeImmutable( $reference ? $reference->format( 'Y-m-d' ) : 'today', wp_timezone() );
// Handles the DateInterval bug in which months days overflow to the next month instead of staying in the current month.
// P1M to Jan 31 gives you Mar 3 instead of Feb 28.
// So we deconstruct the period into years, months, and days, and then add them back separately.
$months = $sign * ( $interval->y * 12 + $interval->m );
$days = $sign * $interval->d;
// Adding x months to today and asking for the last day of that month, then clamping the day to today if it exceeds it.
$end_of_month = $today->modify( sprintf( 'last day of %+d months', $months ) );
$resolved = $end_of_month->setDate(
(int) $end_of_month->format( 'Y' ),
(int) $end_of_month->format( 'n' ),
// Asking for min will get us the correct end of month if we're about to overflow, or the actual date.
// Because adding P1M to Jan 17 should give you Feb 17 but adding P1M to Jan 28-31 should give you Feb 28 (or Feb 29 on leap years).
min( (int) $today->format( 'j' ), (int) $end_of_month->format( 'j' ) )
);
// Add the days back from the original interval.
return $resolved->modify( sprintf( '%+d days', $days ) )->format( 'Y-m-d' );
}