prefix . 'aieo_push_dispatch'; if ( (string) $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $disp ) ) !== $disp ) { return null; } if ( $user_id > 0 ) { $where = 'user_id = %d'; $val = $user_id; } elseif ( '' !== $email ) { $where = 'recipient_email = %s'; $val = $email; } else { return null; } $limit = (int) self::MAX_SCAN; $sql = "(SELECT clicked_at AS ts FROM `{$disp}` WHERE {$where} AND clicked_at IS NOT NULL ORDER BY clicked_at DESC LIMIT {$limit}) UNION ALL (SELECT opened_at AS ts FROM `{$disp}` WHERE {$where} AND opened_at IS NOT NULL ORDER BY opened_at DESC LIMIT {$limit})"; $rows = $wpdb->get_col( $wpdb->prepare( $sql, $val, $val ) ); if ( count( $rows ) < self::MIN_EVENTS ) { return null; } $hist = array_fill( 0, 24, 0 ); foreach ( $rows as $ts ) { if ( empty( $ts ) ) { continue; } $local = get_date_from_gmt( (string) $ts ); $h = (int) substr( $local, 11, 2 ); if ( $h >= 0 && $h <= 23 ) { $hist[ $h ]++; } } $best = 0; $max = -1; foreach ( $hist as $h => $n ) { if ( $n > $max ) { $max = $n; $best = $h; } } return ( $max >= 1 ) ? (int) $best : null; } public static function delay_to_hour( $best_hour ) { $best = max( 0, min( 23, (int) $best_hour ) ); if ( $best === (int) wp_date( 'G' ) ) { return 0; } try { $tz = wp_timezone(); $now = new \DateTime( 'now', $tz ); $tgt = clone $now; $tgt->setTime( $best, 0, 0 ); if ( $tgt <= $now ) { $tgt->modify( '+1 day' ); } return max( 0, $tgt->getTimestamp() - $now->getTimestamp() ); } catch ( \Throwable $e ) { $now_h = (int) wp_date( 'G' ); return ( $best === $now_h ) ? 0 : ( ( ( $best - $now_h + 24 ) % 24 ) * HOUR_IN_SECONDS ); } } }