/
home
/
assocoweys
/
comgk
/
wp-content
/
plugins
/
google-site-kit
/
includes
/
Core
/
Email_Reporting
/
Upload File
HOME
<?php /** * Class Google\Site_Kit\Core\Email_Reporting\Frequency_Planner * * @package Google\Site_Kit\Core\Email_Reporting * @copyright 2025 Google LLC * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 * @link https://sitekit.withgoogle.com */ namespace Google\Site_Kit\Core\Email_Reporting; use DateInterval; use DateTimeImmutable; use DateTimeZone; use InvalidArgumentException; use Google\Site_Kit\Core\User\Email_Reporting_Settings; /** * Calculates the next occurrence for email reporting schedules. * * @since 1.167.0 * @access private * @ignore */ class Frequency_Planner { /** * Trigger hour for email reports. * * @since 1.179.0 * @var int */ const TRIGGER_HOUR = 9; /** * Calculates the next run timestamp for a given frequency. * * @since 1.167.0 * * @param string $frequency Frequency to calculate for. * @param int $timestamp Base UNIX timestamp. * @param DateTimeZone $time_zone Site timezone. * @return int UNIX timestamp for the next run. * @throws InvalidArgumentException When an unsupported frequency is provided. */ public function next_occurrence( $frequency, $timestamp, DateTimeZone $time_zone ) { switch ( $frequency ) { case Email_Reporting_Settings::FREQUENCY_WEEKLY: return $this->get_next_weekly_occurrence( $timestamp, $time_zone ); case Email_Reporting_Settings::FREQUENCY_MONTHLY: return $this->get_next_monthly_occurrence( $timestamp, $time_zone ); case Email_Reporting_Settings::FREQUENCY_QUARTERLY: return $this->get_next_quarterly_occurrence( $timestamp, $time_zone ); } throw new InvalidArgumentException( sprintf( 'Unsupported frequency "%s".', $frequency ) ); } /** * Gets the next weekly occurrence honouring the site "week starts on" setting. * * @param int $timestamp Current timestamp. * @param DateTimeZone $time_zone Site timezone. * @return int Next weekly occurrence timestamp. */ private function get_next_weekly_occurrence( $timestamp, DateTimeZone $time_zone ) { $start_of_week = (int) get_option( 'start_of_week', 0 ); $current = $this->immutable_from_timestamp( $timestamp, $time_zone ); // Anchor scheduling to the trigger hour. $day_start = $current->setTime( self::TRIGGER_HOUR, 0, 0 ); // ISO weekday index where Sunday=0 and Saturday=6, matching WordPress' start_of_week option. $current_wday = (int) $current->format( 'w' ); // Figure out how many days to move forward to land on the configured week start. $days_until_target = ( $start_of_week - $current_wday + 7 ) % 7; // If today is already the target weekday but the time has passed, shift to the following week. if ( 0 === $days_until_target && $current >= $day_start ) { $days_until_target = 7; } $next = $day_start->add( new DateInterval( 'P' . $days_until_target . 'D' ) ); return $next->getTimestamp(); } /** * Gets the next monthly occurrence (first day of next month at the trigger hour). * * @param int $timestamp Current timestamp. * @param DateTimeZone $time_zone Site timezone. * @return int Next monthly occurrence timestamp. */ private function get_next_monthly_occurrence( $timestamp, DateTimeZone $time_zone ) { $current = $this->immutable_from_timestamp( $timestamp, $time_zone ); $next_month = $current ->setTime( self::TRIGGER_HOUR, 0, 0 ) ->modify( 'first day of next month' ); return $next_month->getTimestamp(); } /** * Gets the next quarterly occurrence (first day of the next quarter at the trigger hour). * * @param int $timestamp Current timestamp. * @param DateTimeZone $time_zone Site timezone. * @return int Next quarterly occurrence timestamp. */ private function get_next_quarterly_occurrence( $timestamp, DateTimeZone $time_zone ) { $current = $this->immutable_from_timestamp( $timestamp, $time_zone )->setTime( self::TRIGGER_HOUR, 0, 0 ); // Calendar month number in the local timezone (January=1 … December=12). $current_month = (int) $current->format( 'n' ); // Translate month into its offset within the quarter (0 => first month, 1 => second, 2 => third). $position = ( ( $current_month - 1 ) % 3 ); $months_to_add = 3 - $position; $next_quarter = $current->add( new DateInterval( 'P' . $months_to_add . 'M' ) ); // After jumping to the quarter’s first month, land on day 1 at the trigger hour. $next_quarter = $next_quarter->modify( 'first day of this month' ); return $next_quarter->getTimestamp(); } /** * Creates a timezone-adjusted immutable date. * * @param int $timestamp Base timestamp. * @param DateTimeZone $time_zone Site timezone. * @return DateTimeImmutable DateTimeImmutable instance. */ private function immutable_from_timestamp( $timestamp, DateTimeZone $time_zone ) { return ( new DateTimeImmutable( '@' . $timestamp ) )->setTimezone( $time_zone ); } }