Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I just setup W3 Total Cache S3 CDN (origin push) and most of the URLs are being rewritten correctly but we have some custom plugins where the URLs are not being rewritten. How do I grab the rewritten URL of W3TC from another plugin? I'm currently using the following code to grab the image:

wp_get_attachment_image_src( get_post_thumbnail_id(), 'car-thumb');

I'm assuming there is a filter of some sort that just replaces the original "origin" url with the asset URL on the S3 bucket but I've been unable to find where in the code.

share|improve this question

put on hold as off-topic by mrwweb, ialocin, birgire, Pieter Goosen, Johannes Pille yesterday

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "Your question should be specific to WordPress. Generic PHP/JS/HTML/CSS questions might be better asked at Stack Overflow or another appropriate site of the Stack Exchange network. Third party plugins and themes are off topic." – mrwweb, ialocin, birgire, Pieter Goosen, Johannes Pille
If this question can be reworded to fit the rules in the help center, please edit the question.

    
did you get this to work somehow? –  pkyeck Jun 26 '13 at 20:57

3 Answers 3

The W3 Total Cache plugin changes the URL of various files in /w3-total-cache/lib/W3/Plugin/Cdn.php in the function *ob_callback*. It uses a series of callbacks to modify an output buffer. The code runs like this:

  • w3_total_cache.php calls $root->run();
  • W3_Root::run calls $plugin->run() for each plugin in $this->_loaded_plugins
  • W3_Plugin_TotalCache::run starts an output buffer which calls W3_Plugin_TotalCache::ob_callback
  • W3_Plugin_TotalCache::ob_callback calls w3tc_do_ob_callbacks() which runs any callback stored in $GLOBALS['_w3tc_ob_callbacks']
  • The CDN adds it's own callback to that global in W3_Plugin_Cdn::run. That callback is W3_Plugin_Cdn::ob_callback

Which callbacks then run is unfortunately hard coded in this line: $buffer = w3tc_do_ob_callbacks(array('minify', 'newrelic', 'cdn', 'browsercache', 'pagecache'), $buffer);

Because this is hard coded, if you ever need to modify what is included and what isn't, you'll have to change their callback.

Example:

I have a plugin that exports JSON, and the CDN aspect of W3 Total Cache wasn't changing any URLs for JSON requests. It turns out that my output was failing the w3_is_xml($buffer) test.

I fixed it by turning their single CDN callback into multiples, like this:

// Modify the output buffer callbacks of W3 Total Cache to work with the JSON API
if (!empty($GLOBALS['_w3tc_ob_callbacks']) && isset($GLOBALS['_w3tc_ob_callbacks']['cdn'])) {
    // Back-up the original value of $GLOBALS['_w3tc_ob_callbacks']['cdn']
    // This should be W3_Plugin_Cdn::ob_callback
    $this->cdn_ob_callback = $GLOBALS['_w3tc_ob_callbacks']['cdn'];

    // Replace $GLOBALS['_w3tc_ob_callbacks']['cdn'] with out own method
    // which will call the original callback in between two of our own
    $GLOBALS['_w3tc_ob_callbacks']['cdn'] = array($this, 'do_multiple_cdn_ob_callbacks');
}

Then doing the changes I need, making sure to call their original callback in the middle.

public function do_multiple_cdn_ob_callbacks(&$buffer) {
    // Frist run our own callback to add an XML string to the buffer
    // so that the content passes the w3_is_xml($buffer) test
    $buffer = $this->w3_total_cache_ob_callback_start($buffer);

    // Next run the original callback, which will replace the asset URLs
    $buffer = call_user_func($this->cdn_ob_callback, $buffer);

    // Finally, run another callback of our own to remove the XML string
    $buffer = $this->w3_total_cache_ob_callback_end($buffer);
    return $buffer;
}
share|improve this answer

I had the same issues and couldn't get an answer either. I did however find where in the database WP is storing the entries for the attached images and used that to create my own rewritten URLs.

If you look in the _postmeta table there is a meta_key "_wp_attached_file" that stores the folder path to the attached images. With this information I only needed to add the URL structure for where our S3 bucket is located.

global $postid;
$bucketName = "your_bucket_name_goes_here";
$postThumbNailID = get_post_meta($post->ID, '_thumbnail_id');
$postThumbNailUrl = get_post_meta($postThumbNailID[0], '_wp_attached_file');
$s3BucketURL = "http://".$bucketName.".s3.amazonaws.com/files/".$postThumbNailUrl[0];
share|improve this answer
1  
Where did you put this code? This doesn't look like a complete solution to me. –  s_ha_dum Feb 14 '13 at 20:52

I had a similar issue when rendering a template part.

I had to invoke the W3_Plugin_Cdn plugin programmatically.

As correctly stated by Tyler V., the w3_is_xml($buffer) will fail if $buffer doesn't look like HTML or XML, that's why I'm putting <html> at the beginning of the template part.

Here's an example on how I did.

if (class_exists('W3_Plugin_Cdn')) {
    $cdn_handler = new W3_Plugin_Cdn();
    ob_start();
    echo '<html>';
    get_template_part($templatepart, $templatepartdetail);
    $buffer = ob_get_contents();
    $cdn_handler->ob_callback($buffer);
    $buffer = substr($buffer, strlen('<html>'));
    ob_end_clean();
    echo $buffer;
}
share|improve this answer

Not the answer you're looking for? Browse other questions tagged or ask your own question.