Plugin Update breaks site images



  • Hi Guys,

    I've noticed this happen now on a few Media Cloud updates (except for the previous v3.1.3) where the update process resets the URL of images to the local server and once the update completes, all of our theme related images (logos, etc..) are broken/missing because they're pointing to the local server rather than our CDN address configured within Media Cloud.

    Media Library images do in-fact revert back to the CDN address once the update process completes however images configured within our themes custom settings do not.

    Obviously, this isn't a good thing to be happening on a prod site. Wondering why this happens and why it wasn't happening previously.

    Fix?



  • Suggestion, deactivating the plugin should not reset the URL's for images being used on the site, period. If anything, deactivation should keep all image URL's as is and all future images would then be stored locally.

    This wasn't a problem in v2, only an issue since v3 was released.

    Please advise.



  • @Dcipher

    When using the customizer (which is what I assume you mean by using custom settings) the URL gets baked in because it's not an attachment, it's a URL that actually stored as a setting.

    For attachments, meaning media library items, the URL generation is dynamic and that hasn't changed since 2.x. Deactivating 2.x would most certainly reset your attachment URLs to whatever they were at the moment you saved the post. So if your posts were using local image URLs, that's what they would reset to. If you created a post while Media Cloud was activate, then the URLs would be saved with whatever URL Media Cloud would have been generating at the moment the post was saved.

    For example, if you added Media Cloud to an existing site with existing posts and existing media, the URLs in those existing posts don't get replaced in the database when you import the media. They are replaced on the "fly" when a post is viewed. So deactivating Media Cloud deactivates the URL rewriting for "old posts".

    Any new posts after Media Cloud is setup and running will have saved whatever the URL media cloud generates in the post so deactivating Media Cloud wouldn't have any effect.

    I've verified this on 2.x and 3.x.

    An as far as I know, 2.x didn't have very good support for images added in customizer. Mostly because customizer wasn't, and still isn't, a feature I used much when building sites for clients.

    I'll look into adding a WP-CLI command to rewrite URLs in existing posts in the database which would avoid the issue for "old posts".



  • Thanks for the reply @jong.

    So, we aren't using WP Customizer to add logo image URL's, our theme in fact uses the Redux framework to manage theme specific customisations and configurations, which also includes a section for site logos to be configured including standard, retina, and mobile logo images.

    This also does a similar thing where it uses the image URL, based on the metafile stored in the WP media library, which in our case, all images in the WP media library are stored in S3 (no local server copies) and have a public URL assigned using our configured CDN FQDN.

    Upon updating Media Cloud, we notice that these URL's found in the logo configuration section, reset to the original local server URI path (the path it took on prior to it being offloaded to S3 and deleted from local storage) however they don't update to the correct URL after the update completes. Oddly enough, this wasn't a problem with updating to versions 3.1.1 and 3.1.3 (v3.x versions prior and post have cause problems. v2.x never caused an issue on update).

    I hope this adds further context and clarity to the problem.

    Many thanks in advance.



  • @Dcipher

    I don't know anything about the redux framework so you are going to have to show me some code or a video of what the issue is.



  • @Dcipher

    So I installed redux and messed around with it, but I want to be clear on how you are using it because what I saw of it, it is working as it is intended.

    I'm assuming you created a config with media fields that looked something like:

    Redux::setSection($opt_name, [
        'title' => 'Hero Settings',
        'id'    => 'hero-settings',
        'desc'  => '',
        'icon'  => 'el el-picture'
    ]);
    
    Redux::setSection($opt_name, [
        'title'      => 'Hero Media',
        'id'         => 'hero-settings-media',
        'desc'       => '',
        'subsection' => true,
            'fields' => [
                [
                    'id'       => 'hero-image',
                    'type'     => 'media',
                    'url'      => true,
                    'title'    => 'Hero Image',
                    'desc'     => '',
                    'subtitle' => '',
                    'default'  => ['url' => 'https://s.wordpress.org/style/images/codeispoetry.png'],
                ],
            ]
    ]);
    

    And then on the front end, you are displaying this field:

    <?php global $reduxOptions; ?>
    <img src="<?php echo $reduxOptions['hero-image']['url'] ?>">
    

    So after setting this up, I did the following:

    • Activated Media Cloud
    • Set the hero image to an uploaded image
    • Verified the hero was rendering with the cloud image
    • Deactivated media cloud
    • Verified the hero was now rendering with the local image
    • Reactivated media cloud
    • Saw the issue where redux will still displaying the local image

    Honestly, these feels like a bug with Redux. So I did some debugging.

    Redux constantly verifies media URLs in media fields for some unknown reason. If you look at line 2212 in ReduxCore/framework.php:

    // CORRECT URLS if media URLs are wrong, but attachment IDs are present.
    if ( $field['type'] == "media" ) {
        if ( isset ( $this->options[ $field['id'] ]['id'] ) && isset ( $this->options[ $field['id'] ]['url'] ) && ! empty ( $this->options[ $field['id'] ]['url'] ) && strpos( $this->options[ $field['id'] ]['url'], str_replace( 'http://', '', WP_CONTENT_URL ) ) === false ) {
            $data = wp_get_attachment_url( $this->options[ $field['id'] ]['id'] );
    
            if ( isset ( $data ) && ! empty ( $data ) ) {
                $this->options[ $field['id'] ]['url']       = $data;
                $data                                       = wp_get_attachment_image_src( $this->options[ $field['id'] ]['id'], array(
                    150,
                    150
                ) );
                $this->options[ $field['id'] ]['thumbnail'] = $data[0];
                $doUpdate                                   = true;
            }
        }
    }
    

    This check happens on every admin_init. And the key bit of the check is this part: strpos( $this->options[ $field['id'] ]['url'], str_replace( 'http://', '', WP_CONTENT_URL ) ) === false ). So this basically is saying if the media field's URL contains the default wordpress content url, eg. https://yourlocalwebsite.com/app/uploads/, then don't update the URL because it must be right.

    So anytime you load the WordPress admin, the admin_init action fires, which then causes Redux to "validate" its settings. When you upgrade a plugin, the admin_init hook gets fired between when the previous version of the plugin is activated and the new one is installed/activated, so Redux will alter the URL in that gap. And once it is altered, their check for WP_CONTENT_URL will prevent it from updating the URL again after the new version is activated.

    If you remove the WP_CONTENT_URL check from that line, it works as it should. My honest opinion is that it shouldn't even be doing this at all and I would personally remove that whole chunk of code because wtf.

    So this is a bug/bad design choice with Redux and doesn't have anything to do with Media Cloud.



  • Hey @jong, Brilliant find!

    In short, yes, that's how Redux is implemented on our end and we're seeing more and more premium themes that are using it so this would no doubt be an issue for others using Media Cloud or even other similar media offload plugins.

    I greatly appreciate the level of depth and detail you went to here. I'll be raising this with the Redux team (with full credit to your troubleshooting efforts) for (fingers-crossed) a fix.

    In the interim, we'll go ahead and make some changes to the snippet you provided and see if we can get it to behave as it should because right now, we can't auto update Media Cloud without breaking logos.

    Thanks again and kudos for the brilliant effort and work!


Log in to reply