'object', 'properties' => array( 'start' => array( 'type' => 'string' ), 'end' => array( 'type' => 'string' ), ), ); } /** * Gets the default value for a newly created condition of this type. * * @return mixed */ public function default_value() { return array( 'start' => null, 'end' => null, ); } /** * Evaluates the condition against the given context. * * @param Context $context Request context value object. * @param string $operator Operator identifier. * @param mixed $value Configured value. * @return bool */ public function evaluate( Context $context, string $operator, $value ): bool { $tz = $context->datetime->getTimezone(); $start = self::parse_bound( $value['start'] ?? null, $tz, false ); $end = self::parse_bound( $value['end'] ?? null, $tz, true ); $now = $context->datetime; $in = true; if ( $start && $now < $start ) { $in = false; } if ( $end && $now > $end ) { $in = false; } return 'not_between' === $operator ? ! $in : $in; } /** * Parses a range bound into a DateTimeImmutable in the given timezone. * * The editor stores whole dates (`YYYY-MM-DD`). Both bounds are inclusive, * so a date-only end bound means the *end* of that day — otherwise the block * would disappear at midnight at the start of its last day. * * @param mixed $value Date string or DateTimeInterface. * @param \DateTimeZone $tz Target timezone. * @param bool $is_end Whether this is the end bound. * @return \DateTimeImmutable|null */ public static function parse_bound( $value, \DateTimeZone $tz, bool $is_end ): ?\DateTimeImmutable { if ( $value instanceof \DateTimeInterface ) { return new \DateTimeImmutable( $value->format( 'Y-m-d H:i:s' ), $tz ); } if ( ! is_string( $value ) || '' === $value ) { return null; } try { $date = new \DateTimeImmutable( $value, $tz ); } catch ( \Throwable $e ) { return null; } if ( $is_end && 1 === preg_match( '/^\d{4}-\d{2}-\d{2}$/', $value ) ) { $date = $date->setTime( 23, 59, 59, 999999 ); } return $date; } }