• Resolved flynsarmy

    (@flynsarmy)


    I have CloudFront CDN (push) enabled on W3 Total Cache. When I add an image to my media library, the image is uploaded to the CDN and displays correctly on my blog.

    When I broadcast a post that has image attachments with ThreeWP Broadcast, the new attachments aren’t being picked up by W3TC and so aren’t being uploaded to the CDN and we get 404’s on our site as a result.

    Looking in /path/to/wp-content/plugins/w3-total-cache/lib/W3/Plugin/Cdn.php I see

    add_filter('update_attached_file', array(
        &$this,
        'update_attached_file'
    ));
    ...
    function update_attached_file($attached_file) {
        $files = $this->_get_common()->get_files_for_upload($attached_file);
        $files = apply_filters('w3tc_cdn_update_attachment', $files);
    
        $results = array();
    
        $this->_get_common()->upload($files, true, $results);
    
        return $attached_file;
    }

    I believe your copy_attachment method in /path/to/wp-content/plugins/threewp-broadcast/ThreeWP_Broadcast.php needs to trigger this filter by calling update_attached_file below your if ( $o->attachment_data->file_metadata ) check.

    I haven’t tested, but perhaps:

    // 3. Overwrite the metadata that needs to be overwritten with fresh data.
    			$this->debug( 'Copy attachment: Updating metadata.' );
    			wp_update_attachment_metadata( $o->attachment_id,  $attach_data );
    		}
    
    		update_attached_file($o->attachment_id, $target);

    https://www.ads-software.com/plugins/threewp-broadcast/

Viewing 8 replies - 1 through 8 (of 8 total)
  • Plugin Author edward_plainview

    (@edward_plainview)

    Since I have neither w3tc nor a CDN, maybe you could test the code and then get back to me if it works?

    I just tested this. It did not seem to change anything for me. I’m using ThreeWP and w3TC W3 Total Cache with Rackspace Cloud Hosting CDN.

    Is $target a variable I should change? I’m not sure I understand the edit, but I would like to.

    My manual workaround is to go to the media library and “purge the CDN” for the image listed.

    Thread Starter flynsarmy

    (@flynsarmy)

    @rtklwm That’s not the only problem. When an image-filled post is broadcasted to multiple sites, my code (if it worked) would cause each attachment to be sent to the CDN one at a time for every image for every site. This can easily trigger a load balancer timeout resulting in the post only being created on some sites or only being partially created on some sites.

    Instead I think we need to use an event hook that is triggered after a post is broadcasted. Then bulk upload the way the W3TC – CDN – Upload Attachments</em. button works. I haven’t looked into how to do this yet.

    Thread Starter flynsarmy

    (@flynsarmy)

    Digging further. The function I mentioned above is export_library in /path/to/wp-content/plugins/w3-total-cache/lib/W3/Plugin/CdnAdmin.php. We need to replicate that functionality.

    We can hook into broadcast’s threewp_broadcast_broadcasting_modify_post action and need to pass to w3_instance('W3_Plugin_CdnCommon')->upload() an array of files that look like:

    [
        [
            'local_path' => '/path/to/wp-content/uploads/2012/07/Comfit2.jpg',
            'remote_path' => 'wp-content/uploads/2012/07/Comfit2.jpg',
            'original_url' => 'https://mysite.com/path/to/wp-content/uploads/2012/07/Comfit2.jpg',
        ],
        [
            'local_path' => '/path/to/wp-content/uploads/2012/07/Comfit2-190x100.jpg',
            'remote_path' => 'wp-content/uploads/2012/07/Comfit2-190x100.jpg',
            'original_url' => 'https://mysite.com/path/to/wp-content/uploads/2012/07/Comfit2-190x100.jpg',
        ],
        ...
    ]

    This shouldn’t be too difficult to figure out. I’ll keep you posted.

    Plugin Author edward_plainview

    (@edward_plainview)

    There’s a better hook f?r that:

    threewp_broadcast_broadcasting_before_restore_current_blog

    It is called with the $action parameter, which contains the following interesting data:

    $bcd = $action->broadcasting_data;
    $bcd->copied_attachments <– array of old and new attachment data.

    Thread Starter flynsarmy

    (@flynsarmy)

    After a whole lot of debugging I believe I’ve solved the conflict between ThreeWP Broadcast and W3TC with CDN push enabled. Below is what you’ll need in your functions.php:

    // Fixes https://core.trac.www.ads-software.com/ticket/25650
    // This is required due to a conflict between ThreeWP Broadcast and W3TC when
    // W3TC uses CDN push.
    //
    // When broadcast calls switch_to_blog() during a broadcast, W3TC calls
    // wp_upload_dir() to deterine where to upload the new file. This path will
    // contain the URL of the old blog due to WP_CONTENT_URL constant being
    // wrong.
    add_action('switch_blog', function($new_blog, $prev_blog_id) {
    	update_option( 'upload_url_path',  get_option('siteurl') . '/wp-content/uploads');
    }, 10, 2);

    Make sure to change /wp-content/uploads to the location of your uploads directory if you’re using a custom directory.

    Thread Starter flynsarmy

    (@flynsarmy)

    I’ve whipped up a better version of my above script. This version deletes the option from each site after a broadcast has completed so that the_post_thumbnail() doesn’t break. It also lessens the risk of things breaking if a rogue plugin uses switch_to_blog() without a matching restore_current_blog().

    /**
     * Fixes https://core.trac.www.ads-software.com/ticket/25650
     * This is required due to a conflict between ThreeWP Broadcast and W3TC when
     * W3TC uses CDN push.
     *
     * When broadcast calls switch_to_blog() during a broadcast, W3TC calls
     * wp_upload_dir() to deterine where to upload the new file. This path will
     * contain the URL of the old blog due to WP_CONTENT_URL constant being
     * wrong.
     *
     * @param  int  $new_blog  New blog iD
     * @param  int  $old_blog  Old blog ID
     */
    add_action('switch_blog', function($new_blog, $prev_blog_id) {
    	// We only want to set this option during a broadcast. We don't want the option to
    	// exist at all let alone be used outside of broadcasts as it affects wp_upload_dir()
    	// method.
    	if ( \threewp_broadcast\ThreeWP_Broadcast::instance()->is_broadcasting() )
    		update_option( 'upload_url_path',  get_option('siteurl') . '/wp-content/uploads');
    }, 10, 2);
    
    /**
     * Now that broadcasting has finished, we need to remove the upload_url_path option
     * from each site it was added to, or the_post_thumbnail() URLs will be broken because
     * they use /blog/files/2015/05/foo.jpg instead of /blog/wp-content/uploads/2015/05/foo.jpg
     *
     * Run at priority 1000 so it'll execute after a broadcast has completed. If we run this
     * before broadcast is completed, the above switch_blog action will execute because
     * is_broadcasting() will still be true.
     *
     * @param  threewp_broadcast\broadcasting_data  $bcd
     */
    add_filter('threewp_broadcast_broadcast_post', function($bcd) {
    	// For nested broadcasts. Just in case.
    	switch_to_blog( $bcd->parent_blog_id );
    
    	foreach( $bcd->blogs as $child_blog )
    	{
    		$child_blog->switch_to();
    		delete_option('upload_url_path');
    		$child_blog->switch_from();
    	}
    
    	delete_option('upload_url_path');
    	restore_current_blog();
    	delete_option('upload_url_path');
    }, 1000);
    Plugin Author edward_plainview

    (@edward_plainview)

    We’ve spoken over e-mail and we came to the conclusion that this is best left as a plugin.

    Or rather: I stated and you agreed. ??

Viewing 8 replies - 1 through 8 (of 8 total)
  • The topic ‘Broadcasted attachments W3TC CDN’ is closed to new replies.