Skip to content

Commit

Permalink
Merge pull request #6105 from Automattic/staging
Browse files Browse the repository at this point in the history
Production release: v20250121.0
  • Loading branch information
WPprodigy authored Jan 21, 2025
2 parents ee31eeb + 6bbff68 commit ec2d0a1
Show file tree
Hide file tree
Showing 10 changed files with 186 additions and 63 deletions.
3 changes: 1 addition & 2 deletions cron/cron-control/.github/workflows/ci-grunt.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ env:

jobs:
build:
if: "!contains(github.event.head_commit.message, '[ci skip]')"
name: Run Grunt tasks
runs-on: ubuntu-latest
steps:
Expand All @@ -24,7 +23,7 @@ jobs:
uses: actions/[email protected]
with:
node-version: ${{ env.NODE_VERSION }}
caching: true
cache: npm

- name: Install dependencies
run: npm ci --ignore-scripts
Expand Down
29 changes: 9 additions & 20 deletions cron/cron-control/.github/workflows/ci-php.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@ jobs:
test:
name: Run tests
runs-on: ubuntu-latest
if: "!contains(github.event.head_commit.message, '[ci skip]')"
strategy:
fail-fast: false
matrix:
php:
- "7.4"
- "8.0"
- "8.1"
- "8.2"
- "8.3"
- "8.4"
wpmu:
- "0"
- "1"
Expand All @@ -34,6 +36,9 @@ jobs:
- 3306
options: --health-cmd="healthcheck.sh --innodb_initialized" --health-interval=5s --health-timeout=2s --health-retries=3
steps:
- name: Install svn
run: sudo apt-get update && sudo apt-get install -y subversion

- name: Check out source code
uses: actions/[email protected]

Expand All @@ -42,24 +47,8 @@ jobs:
with:
php-version: ${{ matrix.php }}

- name: Get composer cache directory
id: composer-cache
run: echo "::set-output name=dir::$(composer config cache-files-dir)"

- name: Cache Composer packages
uses: actions/[email protected]
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-php-${{ matrix.php }}-${{ hashFiles('**/composer.lock') }}
restore-keys: |
${{ runner.os }}-php-${{ matrix.php }}
${{ runner.os }}-php-
- name: Validate composer.json and composer.lock
run: composer validate

- name: Install dependencies
run: composer install --prefer-dist --no-progress --no-interaction --ignore-platform-reqs
- name: Install PHP Dependencies
uses: ramsey/[email protected]

- name: Verify MariaDB connection
run: |
Expand Down
21 changes: 3 additions & 18 deletions cron/cron-control/.github/workflows/phpcs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,32 +12,17 @@ jobs:
codestyle:
name: Run code style check
runs-on: ubuntu-latest
if: "!contains(github.event.head_commit.message, '[ci skip]')"
steps:
- name: Check out source code
uses: actions/[email protected]

- name: Set up PHP
uses: shivammathur/setup-php@v2
with:
php-version: 7.4
php-version: 8.1

- name: Get composer cache directory
id: composer-cache
run: echo "::set-output name=dir::$(composer config cache-files-dir)"

- name: Cache Composer packages
uses: actions/[email protected]
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-php-7.4-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-php-7.4

- name: Validate composer.json and composer.lock
run: composer validate

- name: Install dependencies
run: composer install --prefer-dist --no-progress --no-interaction --ignore-platform-reqs
- name: Install PHP Dependencies
uses: ramsey/[email protected]

- name: Add error matcher
run: echo "::add-matcher::$(pwd)/.github/checkstyle-problem-matcher.json"
Expand Down
143 changes: 142 additions & 1 deletion cron/cron-control/__tests__/unit-tests/test-internal-events.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,27 @@ function test_prune_duplicate_events() {
$duplicate_recurring_event2 = Utils::create_test_event( [ 'timestamp' => time() + 200, 'action' => 'recurring_event', 'schedule' => 'hourly', 'interval' => \HOUR_IN_SECONDS ] );
$unique_recurring_event = Utils::create_test_event( [ 'timestamp' => time() + 100, 'action' => 'recurring_event', 'schedule' => 'hourly', 'interval' => \HOUR_IN_SECONDS, 'args' => [ 'unique' ] ] );

// This prevent events starting with `wp_` from being scheduled, like wp_version_check,
// wp_update_plugins or wp_update_themes to avoid affecting the count assertions.
$prevent_wp_cron_events = function ( $event ) {
if ( str_starts_with( $event->hook, 'wp_' ) ) {
return false;
}
return $event;
};

// Filter to block any WordPress core cron events so the test events are isolated.
add_filter( 'schedule_event', $prevent_wp_cron_events );

// Run the pruning.
Cron_Control\Internal_Events::instance()->clean_legacy_data();

// Remove the filter after the pruning calls.
remove_filter( 'schedule_event', $prevent_wp_cron_events );

// Should have 5 events left, and the oldest IDs should have been kept..
$remaining_events = Cron_Control\Events::query( [ 'limit' => 100, 'orderby' => 'ID', 'order' => 'ASC' ] );
$this->assertEquals( 5, count( $remaining_events ), 'correct number of registered events left after pruning' );
$this->assertCount( 5, $remaining_events, 'correct number of registered events left after pruning' );
$this->assertEquals( $remaining_events[0]->get_id(), $original_single_event->get_id(), 'original single event was kept' );
$this->assertEquals( $remaining_events[1]->get_id(), $duplicate_single_event->get_id(), 'duplicate single event was also kept' );
$this->assertEquals( $remaining_events[2]->get_id(), $unique_single_event->get_id(), 'unique single event was kept' );
Expand All @@ -92,4 +107,130 @@ function test_prune_duplicate_events() {
$this->assertEquals( $duplicate_recurring_1->get_status(), Cron_Control\Events_Store::STATUS_COMPLETED, 'duplicate recurring event 1 was marked as completed' );
$this->assertEquals( $duplicate_recurring_2->get_status(), Cron_Control\Events_Store::STATUS_COMPLETED, 'duplicate recurring event 2 was marked as completed' );
}

function test_force_publish_missed_schedules() {
// Define the filter callback to override post status.
$future_insert_filter = function ( $data ) {
if ( 'publish' === $data['post_status'] ) {
$data['post_status'] = 'future'; // Ensure it remains future even if the date is in the past.
}
return $data;
};

// Add the filter to ensure 'future' posts with past dates are not auto-published.
add_filter( 'wp_insert_post_data', $future_insert_filter );

// Create two posts with a 'future' status.
$this->factory()->post->create(
array(
'post_title' => 'Future post that should be published',
'post_status' => 'future',
'post_type' => 'post',
'post_date' => gmdate( 'Y-m-d H:i:s', time() - 1000 ),
)
);

$this->factory()->post->create(
array(
'post_title' => 'Future post that should not be published',
'post_status' => 'future',
'post_type' => 'post',
'post_date' => gmdate( 'Y-m-d H:i:s', time() + 1000 ),
)
);

// Remove the filter after creating the test posts.
remove_filter( 'wp_insert_post_data', $future_insert_filter );

// Count posts with 'future' status before running the method.
$future_posts_before = get_posts(
array(
'post_status' => 'future',
'numberposts' => -1,
)
);

$this->assertCount( 2, $future_posts_before, 'Two posts should be scheduled initially.' );

// Run the function to publish missed schedules.
Cron_Control\Internal_Events::instance()->force_publish_missed_schedules();

// Query posts again after running the function.
$future_posts_after = get_posts(
array(
'post_status' => 'future',
'post_type' => 'post',
'numberposts' => -1,
)
);

$published_posts = get_posts(
array(
'post_status' => 'publish',
'post_type' => 'post',
'numberposts' => -1,
)
);

// Assert counts after the function runs.
$this->assertCount( 1, $future_posts_after, 'One post should still be scheduled.' );
$this->assertCount( 1, $published_posts, 'One post should be published.' );
}

public function test_confirm_scheduled_posts() {
// Create posts with 'future' status.
$future_posts = array(
$this->factory()->post->create(
array(
'post_title' => '1 hour in the future',
'post_status' => 'future',
'post_type' => 'post',
'post_date' => gmdate( 'Y-m-d H:i:s', strtotime( '+1 hour' ) ),
)
),
$this->factory()->post->create(
array(
'post_title' => '2 hours in the future',
'post_status' => 'future',
'post_type' => 'post',
'post_date' => gmdate( 'Y-m-d H:i:s', strtotime( '+2 hours' ) ),
)
),
$this->factory()->post->create(
array(
'post_title' => '3 hours in the future',
'post_status' => 'future',
'post_type' => 'post',
'post_date' => gmdate( 'Y-m-d H:i:s', strtotime( '+3 hours' ) ),
)
),
);

// Clear existing cron events to isolate the test.
Utils::clear_cron_table();

// Query all cron events to confirm none exist.
$events = Cron_Control\Events::query();
$this->assertEmpty( $events, 'No scheduled events should exist initially.' );

// Call the method to confirm scheduled posts.
Cron_Control\Internal_Events::instance()->confirm_scheduled_posts();

// Verify that cron jobs are scheduled for each future post.
foreach ( $future_posts as $future_post_id ) {
$timestamp = wp_next_scheduled( 'publish_future_post', array( $future_post_id ) );
$this->assertNotFalse( $timestamp, "Cron job should be scheduled for post ID: $future_post_id." );
}

// Reschedule one post with a different timestamp and call the method again.
$future_post_gmt_time = strtotime( get_gmt_from_date( get_post( $future_posts[0] )->post_date ) . ' GMT' );
wp_clear_scheduled_hook( 'publish_future_post', array( $future_posts[0] ) );
wp_schedule_single_event( $future_post_gmt_time - 3600, 'publish_future_post', array( $future_posts[0] ) ); // Schedule 1 hour earlier.

Cron_Control\Internal_Events::instance()->confirm_scheduled_posts();

// Verify the post's cron job has been rescheduled to the correct timestamp.
$rescheduled_timestamp = wp_next_scheduled( 'publish_future_post', array( $future_posts[0] ) );
$this->assertEquals( $future_post_gmt_time, $rescheduled_timestamp, 'Cron job for post 1 should be rescheduled to the correct timestamp.' );
}
}
4 changes: 2 additions & 2 deletions cron/cron-control/includes/class-internal-events.php
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ public function is_internal_event( $action ): bool {
public function force_publish_missed_schedules() {
global $wpdb;

$missed_posts = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM {$wpdb->posts} WHERE post_status = 'future' AND post_date <= %s LIMIT 0,100;", current_time( 'mysql', false ) ) );
$missed_posts = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM {$wpdb->posts} p JOIN (SELECT DISTINCT post_type FROM {$wpdb->posts}) AS t ON p.post_type = t.post_type WHERE post_status = 'future' AND post_date <= %s LIMIT 0,100;", current_time( 'mysql', false ) ) );

foreach ( $missed_posts as $missed_post ) {
$missed_post = absint( $missed_post );
Expand All @@ -168,7 +168,7 @@ public function confirm_scheduled_posts() {

do {
$offset = max( 0, $page - 1 ) * $quantity;
$future_posts = $wpdb->get_results( $wpdb->prepare( "SELECT ID, post_date FROM {$wpdb->posts} WHERE post_status = 'future' AND post_date > %s LIMIT %d,%d", current_time( 'mysql', false ), $offset, $quantity ) );
$future_posts = $wpdb->get_results( $wpdb->prepare( "SELECT ID, post_date FROM {$wpdb->posts} p JOIN (SELECT DISTINCT post_type FROM {$wpdb->posts}) AS t ON p.post_type = t.post_type WHERE post_status = 'future' AND post_date > %s LIMIT %d,%d", current_time( 'mysql', false ), $offset, $quantity ) );

if ( ! empty( $future_posts ) ) {
foreach ( $future_posts as $future_post ) {
Expand Down
28 changes: 14 additions & 14 deletions cron/cron-control/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions integrations/integration-vip-config.php
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,12 @@ public function get_site_status() {
if ( $network_site_status ) {
return $network_site_status;
}

$env_config = $this->get_env_config();
if ( isset( $env_config['network_wide_enable'] ) && 'false' === $env_config['network_wide_enable'] ) {
// If network_wide_enable is false, then return disabled status (rather than inheriting) since $network_site_status wasn't found.
return Env_Integration_Status::DISABLED;
}
}

return $this->get_value_from_config( 'env', 'status' );
Expand Down
2 changes: 1 addition & 1 deletion jetpack
Submodule jetpack updated 559 files
9 changes: 6 additions & 3 deletions jetpack.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* Plugin URI: https://jetpack.com
* Description: Security, performance, and marketing tools made by WordPress experts. Jetpack keeps your site protected so you can focus on more important things.
* Author: Automattic
* Version: 14.0
* Version: 14.2.1
* Author URI: https://jetpack.com
* License: GPL2+
* Text Domain: jetpack
Expand All @@ -31,9 +31,12 @@ function vip_default_jetpack_version() {
} elseif ( version_compare( $wp_version, '6.5', '<' ) ) {
// WordPress 6.4.x
return '13.6';
} else {
// WordPress 6.5 and newer.
} elseif ( version_compare( $wp_version, '6.6', '<' ) ) {
// WordPress 6.5.x
return '14.0';
} else {
// WordPress 6.6 and newer.
return '14.2';
}
}

Expand Down
Loading

0 comments on commit ec2d0a1

Please sign in to comment.