Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 45 additions & 43 deletions includes/class-wp-push-syndication-server.php
Original file line number Diff line number Diff line change
Expand Up @@ -1337,69 +1337,71 @@ public function pull_content( $sites = array() ) {

$post_types_processed = array();

if ( count( $posts ) > 0 ) {
if ( is_array( $posts ) && count( $posts ) > 0 ) {
Syndication_Logger::log_post_info( $site_id, $status = 'start_import', $message = sprintf( __( 'starting import for site id %d with %d posts', 'push-syndication' ), $site_id, count( $posts ) ), $log_time = null, $extra = array() );
} else {
Syndication_Logger::log_post_info( $site_id, $status = 'no_posts', $message = sprintf( __( 'no posts for site id %d', 'push-syndication' ), $site_id ), $log_time = null, $extra = array() );
}

foreach( $posts as $post ) {
if ( is_array( $posts ) && ! empty( $posts) ) {
foreach( $posts as $post ) {

if ( ! in_array( $post['post_type'], $post_types_processed ) ) {
remove_post_type_support( $post['post_type'], 'revisions' );
$post_types_processed[] = $post['post_type'];
}

if ( empty( $post['post_guid'] ) ) {
Syndication_Logger::log_post_error( $site_id, $status = 'no_post_guid', $message = sprintf( __( 'skipping post no guid', 'push-syndication' ) ), $log_time = null, $extra = array( 'post' => $post ) );
continue;
}
$post_id = $this->find_post_by_guid( $post['post_guid'], $post, $site );

if ( $post_id ) {
$pull_edit_shortcircuit = apply_filters( 'syn_pre_pull_edit_post_shortcircuit', false, $post, $site, $transport_type, $client );
if ( true === $pull_edit_shortcircuit ) {
Syndication_Logger::log_post_info( $site_id, $status = 'skip_pre_pull_edit_post', $message = sprintf( __( 'skipping post per syn_pre_pull_edit_post_shortcircuit', 'push-syndication' ) ), $log_time = null, $extra = array( 'post' => $post ) );
continue;
if ( ! in_array( $post['post_type'], $post_types_processed ) ) {
remove_post_type_support( $post['post_type'], 'revisions' );
$post_types_processed[] = $post['post_type'];
}
// if updation is disabled continue
if( $this->push_syndicate_settings['update_pulled_posts'] != 'on' ) {
Syndication_Logger::log_post_info( $site_id, $status = 'skip_update_pulled_posts', $message = sprintf( __( 'skipping post update per update_pulled_posts setting', 'push-syndication' ) ), $log_time = null, $extra = array( 'post' => $post ) );

if ( empty( $post['post_guid'] ) ) {
Syndication_Logger::log_post_error( $site_id, $status = 'no_post_guid', $message = sprintf( __( 'skipping post no guid', 'push-syndication' ) ), $log_time = null, $extra = array( 'post' => $post ) );
continue;
}
$post['ID'] = $post_id;
$post_id = $this->find_post_by_guid( $post['post_guid'], $post, $site );

$post = apply_filters( 'syn_pull_edit_post', $post, $site, $client );
if ( $post_id ) {
$pull_edit_shortcircuit = apply_filters( 'syn_pre_pull_edit_post_shortcircuit', false, $post, $site, $transport_type, $client );
if ( true === $pull_edit_shortcircuit ) {
Syndication_Logger::log_post_info( $site_id, $status = 'skip_pre_pull_edit_post', $message = sprintf( __( 'skipping post per syn_pre_pull_edit_post_shortcircuit', 'push-syndication' ) ), $log_time = null, $extra = array( 'post' => $post ) );
continue;
}
// if updation is disabled continue
if( $this->push_syndicate_settings['update_pulled_posts'] != 'on' ) {
Syndication_Logger::log_post_info( $site_id, $status = 'skip_update_pulled_posts', $message = sprintf( __( 'skipping post update per update_pulled_posts setting', 'push-syndication' ) ), $log_time = null, $extra = array( 'post' => $post ) );
continue;
}
$post['ID'] = $post_id;

$result = wp_update_post( $post, true );
$post = apply_filters( 'syn_pull_edit_post', $post, $site, $client );

do_action( 'syn_post_pull_edit_post', $result, $post, $site, $transport_type, $client );
$result = wp_update_post( $post, true );

$updated_post_ids[] = (int) $result;
do_action( 'syn_post_pull_edit_post', $result, $post, $site, $transport_type, $client );

} else {
$pull_new_shortcircuit = apply_filters( 'syn_pre_pull_new_post_shortcircuit', false, $post, $site, $transport_type, $client );
if ( true === $pull_new_shortcircuit ) {
Syndication_Logger::log_post_info( $site_id, $status = 'syn_pre_pull_new_post_shortcircuit', $message = sprintf( __( 'skipping post per syn_pre_pull_edit_post_shortcircuit', 'push-syndication' ) ), $log_time = null, $extra = array( 'post' => $post ) );
continue;
}
$post = apply_filters( 'syn_pull_new_post', $post, $site, $client );
$updated_post_ids[] = (int) $result;

$result = wp_insert_post( $post, true );
} else {
$pull_new_shortcircuit = apply_filters( 'syn_pre_pull_new_post_shortcircuit', false, $post, $site, $transport_type, $client );
if ( true === $pull_new_shortcircuit ) {
Syndication_Logger::log_post_info( $site_id, $status = 'syn_pre_pull_new_post_shortcircuit', $message = sprintf( __( 'skipping post per syn_pre_pull_edit_post_shortcircuit', 'push-syndication' ) ), $log_time = null, $extra = array( 'post' => $post ) );
continue;
}
$post = apply_filters( 'syn_pull_new_post', $post, $site, $client );

do_action( 'syn_post_pull_new_post', $result, $post, $site, $transport_type, $client );
$result = wp_insert_post( $post, true );

if( !is_wp_error( $result ) ) {
update_post_meta( $result, 'syn_post_guid', $post['post_guid'] );
update_post_meta( $result, 'syn_source_site_id', $site_id );
}
do_action( 'syn_post_pull_new_post', $result, $post, $site, $transport_type, $client );

$updated_post_ids[] = (int) $result;
if( !is_wp_error( $result ) ) {
update_post_meta( $result, 'syn_post_guid', $post['post_guid'] );
update_post_meta( $result, 'syn_source_site_id', $site_id );
}

$updated_post_ids[] = (int) $result;
}
}
}

foreach ( $post_types_processed as $post_type ) {
add_post_type_support( $post_type, 'revisions' );
foreach ( $post_types_processed as $post_type ) {
add_post_type_support( $post_type, 'revisions' );
}
}

update_post_meta( $site_id, 'syn_last_pull_time', current_time( 'timestamp', 1 ) );
Expand Down
115 changes: 115 additions & 0 deletions tests/Integration/PullContentTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
<?php
/**
* Tests for the pull_content functionality in WP_Push_Syndication_Server.
*
* @package Automattic\Syndication\Tests
*/

namespace Syndication\Tests;

use Yoast\WPTestUtils\WPIntegration\TestCase as WPIntegrationTestCase;

/**
* Class PullContentTest
*
* @covers WP_Push_Syndication_Server::pull_content
*/
class PullContentTest extends WPIntegrationTestCase {

/**
* Test that pull_content handles non-array posts without PHP warnings.
*
* This tests the fix for PHP warnings that occurred when a client's
* get_posts() method returned a non-array value (e.g., false, null).
*
* @covers WP_Push_Syndication_Server::pull_content
*/
public function test_pull_content_handles_non_array_posts(): void {
global $push_syndication_server;

// Configure mock client to return false.
\Syndication_Mock_Client::set_posts( false );

// Create a site post with pull enabled.
$site_id = $this->factory()->post->create(
array(
'post_type' => 'syn_site',
'post_status' => 'publish',
)
);

// Enable the site for syndication.
update_post_meta( $site_id, 'syn_site_enabled', 'on' );

// Use our mock transport type.
update_post_meta( $site_id, 'syn_transport_type', 'Mock' );

// Get the site post object to pass directly.
$site = get_post( $site_id );

// This should not trigger any PHP warnings.
// If is_array() check is missing, count() on false would warn.
$push_syndication_server->pull_content( array( $site ) );

// Verify the last pull time was still updated.
$last_pull_time = get_post_meta( $site_id, 'syn_last_pull_time', true );
$this->assertNotEmpty( $last_pull_time, 'Last pull time should be updated even when no posts returned' );
}

/**
* Test that pull_content handles null posts without PHP warnings.
*
* @covers WP_Push_Syndication_Server::pull_content
*/
public function test_pull_content_handles_null_posts(): void {
global $push_syndication_server;

\Syndication_Mock_Client::set_posts( null );

$site_id = $this->factory()->post->create(
array(
'post_type' => 'syn_site',
'post_status' => 'publish',
)
);

update_post_meta( $site_id, 'syn_site_enabled', 'on' );
update_post_meta( $site_id, 'syn_transport_type', 'Mock' );

$site = get_post( $site_id );

// Should not trigger warnings.
$push_syndication_server->pull_content( array( $site ) );

$last_pull_time = get_post_meta( $site_id, 'syn_last_pull_time', true );
$this->assertNotEmpty( $last_pull_time );
}

/**
* Test that pull_content handles empty array without issues.
*
* @covers WP_Push_Syndication_Server::pull_content
*/
public function test_pull_content_handles_empty_array(): void {
global $push_syndication_server;

\Syndication_Mock_Client::set_posts( array() );

$site_id = $this->factory()->post->create(
array(
'post_type' => 'syn_site',
'post_status' => 'publish',
)
);

update_post_meta( $site_id, 'syn_site_enabled', 'on' );
update_post_meta( $site_id, 'syn_transport_type', 'Mock' );

$site = get_post( $site_id );

$push_syndication_server->pull_content( array( $site ) );

$last_pull_time = get_post_meta( $site_id, 'syn_last_pull_time', true );
$this->assertNotEmpty( $last_pull_time, 'Last pull time should be updated even with empty posts array' );
}
}
135 changes: 135 additions & 0 deletions tests/Integration/Syndication_Mock_Client.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
<?php
/**
* Mock syndication client for testing.
*
* Named to match the factory's expected format: Syndication_{transport_type}_Client
* Use transport_type 'Mock' to load this client.
*
* @package Automattic\Syndication\Tests
*/

/**
* Mock client for testing pull_content with various return values.
*/
class Syndication_Mock_Client implements Syndication_Client {

/**
* Posts to return from get_posts().
*
* @var mixed
*/
private static $posts_to_return = array();

/**
* Set the posts that get_posts() will return.
*
* @param mixed $posts Posts to return (can be array, false, null, etc.).
*/
public static function set_posts( $posts ) {
self::$posts_to_return = $posts;
}

/**
* Constructor.
*
* @param int $site_id Site ID.
*/
public function __construct( $site_id ) {}

/**
* Get posts from the remote site.
*
* @param array $args Arguments.
* @return mixed
*/
public function get_posts( $args = array() ) {
return self::$posts_to_return;
}

/**
* Create a new post on the remote site.
*
* @param int $post_id Post ID.
* @return bool
*/
public function new_post( $post_id ) {
return false;
}

/**
* Edit a post on the remote site.
*
* @param int $post_id Post ID.
* @param int $ext_id External ID.
* @return bool
*/
public function edit_post( $post_id, $ext_id ) {
return false;
}

/**
* Delete a post on the remote site.
*
* @param int $ext_id External ID.
* @return bool
*/
public function delete_post( $ext_id ) {
return false;
}

/**
* Get a single post from the remote site.
*
* @param int $ext_id External ID.
* @return bool
*/
public function get_post( $ext_id ) {
return false;
}

/**
* Test the connection to the remote site.
*
* @return bool
*/
public function test_connection() {
return true;
}

/**
* Check if a post exists on the remote site.
*
* @param int $ext_id External ID.
* @return bool
*/
public function is_post_exists( $ext_id ) {
return false;
}

/**
* Get client data.
*
* @return array
*/
public static function get_client_data() {
return array(
'id' => 'Mock',
'modes' => array( 'pull' ),
'name' => 'Mock Client',
);
}

/**
* Display settings.
*
* @param object $site Site object.
*/
public static function display_settings( $site ) {}

/**
* Save settings.
*
* @param int $site_id Site ID.
*/
public static function save_settings( $site_id ) {}
}
1 change: 1 addition & 0 deletions tests/bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,5 @@ function (): void {
* Load test dependencies.
*/
require_once __DIR__ . '/Integration/EncryptorTestCase.php';
require_once __DIR__ . '/Integration/Syndication_Mock_Client.php';
}