Skip to content

Ensure edited image sources are backed up when restoring the original image #295

Closed

Description

@felixarntz

Bug Description

Follow-up to #228: When editing an image in WordPress core (related: #158), the original image's sizes are backed up. This is primarily to restore them later. If then the original image is restored again or another round of edits to the same image is saved, the edited image's sizes get backed up. There is no way to restore these via the WordPress UI, but WordPress intentionally does not delete any edits at any point, and it keeps their metadata backups as well.

Our WebP uploads module does not behave in the same way with our _wp_attachment_backup_sources storage: When restoring the original image, the edited image data is not included in that backup anymore, while it is included in core's _wp_attachment_backup_sizes. Note that this problem only concerns the full size in any case, because all sub-size sources are included in WordPress's own storage by definition. But it is a bug we need to fix.

This is probably not critical because there's no way to restore them, but it's still a bug in the WebP uploads module based on how WordPress core works. We do keep the files around as expected, but we don't keep the meta data backup around, which makes it even more inconsistent even with our own approach.

Steps to reproduce

  1. Upload a JPEG image with the WebP Uploads module active. WebP versions are generated in addition to the JPEG versions.
  2. Edit the image through the WordPress UI (e.g. crop, rotate, anything). Then save.
  3. View the attachment's _wp_attachment_backup_sizes and _wp_attachment_backup_sources post meta values. Both have the necessary data stored, the first for all individual sizes (including sources for each size), the latter just the main sources, i.e. for the original image (under full-orig, for consistency with the backup sizes).
  4. Now restore the original.
  5. View the attachment's _wp_attachment_backup_sizes and _wp_attachment_backup_sources post meta values. You will now recognize that the previous edit's file paths etc are present in _wp_attachment_backup_sizes, but not in _wp_attachment_backup_sources - the latter still only has the full-orig data and is missing the hashed data with references to the previously edited image, which is the problem we need to fix here.

Activity

  1. felixarntz commented on Apr 14, 2022

    @felixarntz
    MemberAuthor
  2. mitogh commented on Apr 15, 2022

    @mitogh
    Member

    Hey! @felixarntz thanks for opening this issue, I did some tests and apparently looks like this behavior is the same as having IMAGE_EDIT_OVERWRITE defined to true would you mind double check that you have this constant not defined or set to false, not defined is the default state of this constant.

    When the constant is defined and holds a truthy value, no additional edited images are stored in either the backup sizes and backup sources meta.

    This is value when IMAGE_EDIT_OVERWRITE is not defined or when the value is a falsy value when running your steps with the latest changes from production 3bd51d1.

    • Backup sources after 2 edits

    2022-04-14_19-50

    • Backups sizes after 2 edits

    2022-04-14_19-50_1

    When the constant is defined and holds a truthy value

    Only the original values are stored in both backup sizes and sources when the constant is defined with a truthy value, which seems very closely to what you are describing on the ticket.

    Please let me know what's the result once you run your tests on your end.

  3. felixarntz commented on Apr 18, 2022

    @felixarntz
    MemberAuthor

    @mitogh The constant IMAGE_EDIT_OVERWRITE is not defined in my environment (I'm using the built-in testing environment from the Performance Lab plugin).

    After further testing, I've verified the issue I originally reported is indeed valid. However, it only happens when restoring an image. It does not happen when doing multiple edits to an image, that all works fine.

    Please review all of the following data. First I have the data for doing multiple edits, all of which looks right. Then, the data for doing one edit and restoring the original - that one is the problem. I've updated the issue name to clarify the bug is only about restoring.

    Doing multiple edits

    Here's what I'm seeing, after uploading a new image (ID 4).

    After doing a single edit and saving that

    File name with hash for the new edit

    waffles-e1650305671682.jpg
    

    Output of wp post meta get 4 _wp_attachment_backup_sizes

    array (
      'full-orig' =>
      array (
        'width' => 1800,
        'height' => 1200,
        'file' => 'waffles.jpg',
      ),
      'thumbnail-orig' =>
      array (
        'file' => 'waffles-150x150.jpg',
        'width' => 150,
        'height' => 150,
        'mime-type' => 'image/jpeg',
        'sources' =>
        array (
          'image/jpeg' =>
          array (
            'file' => 'waffles-150x150.jpg',
            'filesize' => 9083,
          ),
          'image/webp' =>
          array (
            'file' => 'waffles-150x150.webp',
            'filesize' => 7566,
          ),
        ),
      ),
      'medium-orig' =>
      array (
        'file' => 'waffles-300x200.jpg',
        'width' => 300,
        'height' => 200,
        'mime-type' => 'image/jpeg',
        'sources' =>
        array (
          'image/jpeg' =>
          array (
            'file' => 'waffles-300x200.jpg',
            'filesize' => 20389,
          ),
          'image/webp' =>
          array (
            'file' => 'waffles-300x200.webp',
            'filesize' => 16372,
          ),
        ),
      ),
      'medium_large-orig' =>
      array (
        'file' => 'waffles-768x512.jpg',
        'width' => 768,
        'height' => 512,
        'mime-type' => 'image/jpeg',
        'sources' =>
        array (
          'image/jpeg' =>
          array (
            'file' => 'waffles-768x512.jpg',
            'filesize' => 97660,
          ),
          'image/webp' =>
          array (
            'file' => 'waffles-768x512.webp',
            'filesize' => 71934,
          ),
        ),
      ),
      'large-orig' =>
      array (
        'file' => 'waffles-1024x683.jpg',
        'width' => 1024,
        'height' => 683,
        'mime-type' => 'image/jpeg',
        'sources' =>
        array (
          'image/jpeg' =>
          array (
            'file' => 'waffles-1024x683.jpg',
            'filesize' => 164783,
          ),
          'image/webp' =>
          array (
            'file' => 'waffles-1024x683.webp',
            'filesize' => 126952,
          ),
        ),
      ),
      '1536x1536-orig' =>
      array (
        'file' => 'waffles-1536x1024.jpg',
        'width' => 1536,
        'height' => 1024,
        'mime-type' => 'image/jpeg',
        'sources' =>
        array (
          'image/jpeg' =>
          array (
            'file' => 'waffles-1536x1024.jpg',
            'filesize' => 353002,
          ),
          'image/webp' =>
          array (
            'file' => 'waffles-1536x1024.webp',
            'filesize' => 268142,
          ),
        ),
      ),
    )
    

    Output of wp post meta get 4 _wp_attachment_backup_sources

    array (
      'full-orig' =>
      array (
        'image/jpeg' =>
        array (
          'file' => 'waffles.jpg',
          'filesize' => 344388,
        ),
        'image/webp' =>
        array (
          'file' => 'waffles.webp',
          'filesize' => 410008,
        ),
      ),
    )
    

    This all looks right. The original sources data is saved within backup sizes and backup sources.

    After doing another edit to the same image and saving that

    File name with hash for the new edit

    waffles-e1650306045124.jpg
    

    Output of wp post meta get 4 _wp_attachment_backup_sizes

    array (
      'full-orig' =>
      array (
        'width' => 1800,
        'height' => 1200,
        'file' => 'waffles.jpg',
      ),
      'thumbnail-orig' =>
      array (
        'file' => 'waffles-150x150.jpg',
        'width' => 150,
        'height' => 150,
        'mime-type' => 'image/jpeg',
        'sources' =>
        array (
          'image/jpeg' =>
          array (
            'file' => 'waffles-150x150.jpg',
            'filesize' => 9083,
          ),
          'image/webp' =>
          array (
            'file' => 'waffles-150x150.webp',
            'filesize' => 7566,
          ),
        ),
      ),
      'medium-orig' =>
      array (
        'file' => 'waffles-300x200.jpg',
        'width' => 300,
        'height' => 200,
        'mime-type' => 'image/jpeg',
        'sources' =>
        array (
          'image/jpeg' =>
          array (
            'file' => 'waffles-300x200.jpg',
            'filesize' => 20389,
          ),
          'image/webp' =>
          array (
            'file' => 'waffles-300x200.webp',
            'filesize' => 16372,
          ),
        ),
      ),
      'medium_large-orig' =>
      array (
        'file' => 'waffles-768x512.jpg',
        'width' => 768,
        'height' => 512,
        'mime-type' => 'image/jpeg',
        'sources' =>
        array (
          'image/jpeg' =>
          array (
            'file' => 'waffles-768x512.jpg',
            'filesize' => 97660,
          ),
          'image/webp' =>
          array (
            'file' => 'waffles-768x512.webp',
            'filesize' => 71934,
          ),
        ),
      ),
      'large-orig' =>
      array (
        'file' => 'waffles-1024x683.jpg',
        'width' => 1024,
        'height' => 683,
        'mime-type' => 'image/jpeg',
        'sources' =>
        array (
          'image/jpeg' =>
          array (
            'file' => 'waffles-1024x683.jpg',
            'filesize' => 164783,
          ),
          'image/webp' =>
          array (
            'file' => 'waffles-1024x683.webp',
            'filesize' => 126952,
          ),
        ),
      ),
      '1536x1536-orig' =>
      array (
        'file' => 'waffles-1536x1024.jpg',
        'width' => 1536,
        'height' => 1024,
        'mime-type' => 'image/jpeg',
        'sources' =>
        array (
          'image/jpeg' =>
          array (
            'file' => 'waffles-1536x1024.jpg',
            'filesize' => 353002,
          ),
          'image/webp' =>
          array (
            'file' => 'waffles-1536x1024.webp',
            'filesize' => 268142,
          ),
        ),
      ),
      'full-1650306045124' =>
      array (
        'width' => 1422,
        'height' => 1200,
        'file' => 'waffles-e1650305671682.jpg',
      ),
      'thumbnail-1650306045124' =>
      array (
        'file' => 'waffles-e1650305671682-150x150.jpg',
        'width' => 150,
        'height' => 150,
        'mime-type' => 'image/jpeg',
        'sources' =>
        array (
          'image/jpeg' =>
          array (
            'file' => 'waffles-e1650305671682-150x150.jpg',
            'filesize' => 9106,
          ),
          'image/webp' =>
          array (
            'file' => 'waffles-e1650305671682-150x127.webp',
            'filesize' => 6462,
          ),
        ),
      ),
      'medium-1650306045124' =>
      array (
        'file' => 'waffles-e1650305671682-300x253.jpg',
        'width' => 300,
        'height' => 253,
        'mime-type' => 'image/jpeg',
        'sources' =>
        array (
          'image/jpeg' =>
          array (
            'file' => 'waffles-e1650305671682-300x253.jpg',
            'filesize' => 25179,
          ),
          'image/webp' =>
          array (
            'file' => 'waffles-e1650305671682-300x253.webp',
            'filesize' => 19346,
          ),
        ),
      ),
      'medium_large-1650306045124' =>
      array (
        'file' => 'waffles-e1650305671682-768x648.jpg',
        'width' => 768,
        'height' => 648,
        'mime-type' => 'image/jpeg',
        'sources' =>
        array (
          'image/jpeg' =>
          array (
            'file' => 'waffles-e1650305671682-768x648.jpg',
            'filesize' => 121138,
          ),
          'image/webp' =>
          array (
            'file' => 'waffles-e1650305671682-768x648.webp',
            'filesize' => 92702,
          ),
        ),
      ),
      'large-1650306045124' =>
      array (
        'file' => 'waffles-e1650305671682-1024x864.jpg',
        'width' => 1024,
        'height' => 864,
        'mime-type' => 'image/jpeg',
        'sources' =>
        array (
          'image/jpeg' =>
          array (
            'file' => 'waffles-e1650305671682-1024x864.jpg',
            'filesize' => 206798,
          ),
          'image/webp' =>
          array (
            'file' => 'waffles-e1650305671682-1024x864.webp',
            'filesize' => 162196,
          ),
        ),
      ),
    )
    

    Output of wp post meta get 4 _wp_attachment_backup_sources

    array (
      'full-orig' =>
      array (
        'image/jpeg' =>
        array (
          'file' => 'waffles.jpg',
          'filesize' => 344388,
        ),
        'image/webp' =>
        array (
          'file' => 'waffles.webp',
          'filesize' => 410008,
        ),
      ),
      'full-1650306045124' =>
      array (
        'image/jpeg' =>
        array (
          'file' => 'waffles-e1650305671682.jpg',
          'filesize' => 427903,
        ),
        'image/webp' =>
        array (
          'file' => 'waffles-e1650305671682.webp',
          'filesize' => 341406,
        ),
      ),
    )
    

    So this actually all looks right. Both the original sources data and the first edit's data is saved within backup sizes and backup sources.

    Doing one edit and then restoring

    Here's what I'm seeing, after uploading a new image (ID 5).

    After doing a single edit and saving that

    File name with hash for the new edit

    pie-e1650306573387.jpg
    

    Output of wp post meta get 5 _wp_attachment_backup_sizes

    array (
      'full-orig' =>
      array (
        'width' => 1800,
        'height' => 1200,
        'file' => 'pie.jpg',
      ),
      'thumbnail-orig' =>
      array (
        'file' => 'pie-150x150.jpg',
        'width' => 150,
        'height' => 150,
        'mime-type' => 'image/jpeg',
        'sources' =>
        array (
          'image/jpeg' =>
          array (
            'file' => 'pie-150x150.jpg',
            'filesize' => 4683,
          ),
          'image/webp' =>
          array (
            'file' => 'pie-150x150.webp',
            'filesize' => 2850,
          ),
        ),
      ),
      'medium-orig' =>
      array (
        'file' => 'pie-300x200.jpg',
        'width' => 300,
        'height' => 200,
        'mime-type' => 'image/jpeg',
        'sources' =>
        array (
          'image/jpeg' =>
          array (
            'file' => 'pie-300x200.jpg',
            'filesize' => 9213,
          ),
          'image/webp' =>
          array (
            'file' => 'pie-300x200.webp',
            'filesize' => 4912,
          ),
        ),
      ),
      'medium_large-orig' =>
      array (
        'file' => 'pie-768x512.jpg',
        'width' => 768,
        'height' => 512,
        'mime-type' => 'image/jpeg',
        'sources' =>
        array (
          'image/jpeg' =>
          array (
            'file' => 'pie-768x512.jpg',
            'filesize' => 38072,
          ),
          'image/webp' =>
          array (
            'file' => 'pie-768x512.webp',
            'filesize' => 16768,
          ),
        ),
      ),
      'large-orig' =>
      array (
        'file' => 'pie-1024x683.jpg',
        'width' => 1024,
        'height' => 683,
        'mime-type' => 'image/jpeg',
        'sources' =>
        array (
          'image/jpeg' =>
          array (
            'file' => 'pie-1024x683.jpg',
            'filesize' => 62880,
          ),
          'image/webp' =>
          array (
            'file' => 'pie-1024x683.webp',
            'filesize' => 26220,
          ),
        ),
      ),
      '1536x1536-orig' =>
      array (
        'file' => 'pie-1536x1024.jpg',
        'width' => 1536,
        'height' => 1024,
        'mime-type' => 'image/jpeg',
        'sources' =>
        array (
          'image/jpeg' =>
          array (
            'file' => 'pie-1536x1024.jpg',
            'filesize' => 129425,
          ),
          'image/webp' =>
          array (
            'file' => 'pie-1536x1024.webp',
            'filesize' => 54176,
          ),
        ),
      ),
    )
    

    Output of wp post meta get 5 _wp_attachment_backup_sources

    array (
      'full-orig' =>
      array (
        'image/jpeg' =>
        array (
          'file' => 'pie.jpg',
          'filesize' => 121123,
        ),
        'image/webp' =>
        array (
          'file' => 'pie.webp',
          'filesize' => 92266,
        ),
      ),
    )
    

    This all looks right. The original sources data is saved within backup sizes and backup sources.

    After restoring the original

    File name (now back to the original)

    pie.jpg
    

    Output of wp post meta get 5 _wp_attachment_backup_sizes

    array (
      'full-orig' =>
      array (
        'width' => 1800,
        'height' => 1200,
        'file' => 'pie.jpg',
      ),
      'thumbnail-orig' =>
      array (
        'file' => 'pie-150x150.jpg',
        'width' => 150,
        'height' => 150,
        'mime-type' => 'image/jpeg',
        'sources' =>
        array (
          'image/jpeg' =>
          array (
            'file' => 'pie-150x150.jpg',
            'filesize' => 4683,
          ),
          'image/webp' =>
          array (
            'file' => 'pie-150x150.webp',
            'filesize' => 2850,
          ),
        ),
      ),
      'medium-orig' =>
      array (
        'file' => 'pie-300x200.jpg',
        'width' => 300,
        'height' => 200,
        'mime-type' => 'image/jpeg',
        'sources' =>
        array (
          'image/jpeg' =>
          array (
            'file' => 'pie-300x200.jpg',
            'filesize' => 9213,
          ),
          'image/webp' =>
          array (
            'file' => 'pie-300x200.webp',
            'filesize' => 4912,
          ),
        ),
      ),
      'medium_large-orig' =>
      array (
        'file' => 'pie-768x512.jpg',
        'width' => 768,
        'height' => 512,
        'mime-type' => 'image/jpeg',
        'sources' =>
        array (
          'image/jpeg' =>
          array (
            'file' => 'pie-768x512.jpg',
            'filesize' => 38072,
          ),
          'image/webp' =>
          array (
            'file' => 'pie-768x512.webp',
            'filesize' => 16768,
          ),
        ),
      ),
      'large-orig' =>
      array (
        'file' => 'pie-1024x683.jpg',
        'width' => 1024,
        'height' => 683,
        'mime-type' => 'image/jpeg',
        'sources' =>
        array (
          'image/jpeg' =>
          array (
            'file' => 'pie-1024x683.jpg',
            'filesize' => 62880,
          ),
          'image/webp' =>
          array (
            'file' => 'pie-1024x683.webp',
            'filesize' => 26220,
          ),
        ),
      ),
      '1536x1536-orig' =>
      array (
        'file' => 'pie-1536x1024.jpg',
        'width' => 1536,
        'height' => 1024,
        'mime-type' => 'image/jpeg',
        'sources' =>
        array (
          'image/jpeg' =>
          array (
            'file' => 'pie-1536x1024.jpg',
            'filesize' => 129425,
          ),
          'image/webp' =>
          array (
            'file' => 'pie-1536x1024.webp',
            'filesize' => 54176,
          ),
        ),
      ),
      'full-1650306659544' =>
      array (
        'width' => 1413,
        'height' => 1200,
        'file' => 'pie-e1650306573387.jpg',
      ),
      'thumbnail-1650306659544' =>
      array (
        'file' => 'pie-e1650306573387-150x150.jpg',
        'width' => 150,
        'height' => 150,
        'mime-type' => 'image/jpeg',
        'sources' =>
        array (
          'image/jpeg' =>
          array (
            'file' => 'pie-e1650306573387-150x150.jpg',
            'filesize' => 4642,
          ),
          'image/webp' =>
          array (
            'file' => 'pie-e1650306573387-150x127.webp',
            'filesize' => 2370,
          ),
        ),
      ),
      'medium-1650306659544' =>
      array (
        'file' => 'pie-e1650306573387-300x255.jpg',
        'width' => 300,
        'height' => 255,
        'mime-type' => 'image/jpeg',
        'sources' =>
        array (
          'image/jpeg' =>
          array (
            'file' => 'pie-e1650306573387-300x255.jpg',
            'filesize' => 11013,
          ),
          'image/webp' =>
          array (
            'file' => 'pie-e1650306573387-300x255.webp',
            'filesize' => 5646,
          ),
        ),
      ),
      'medium_large-1650306659544' =>
      array (
        'file' => 'pie-e1650306573387-768x652.jpg',
        'width' => 768,
        'height' => 652,
        'mime-type' => 'image/jpeg',
        'sources' =>
        array (
          'image/jpeg' =>
          array (
            'file' => 'pie-e1650306573387-768x652.jpg',
            'filesize' => 47666,
          ),
          'image/webp' =>
          array (
            'file' => 'pie-e1650306573387-768x652.webp',
            'filesize' => 20348,
          ),
        ),
      ),
      'large-1650306659544' =>
      array (
        'file' => 'pie-e1650306573387-1024x870.jpg',
        'width' => 1024,
        'height' => 870,
        'mime-type' => 'image/jpeg',
        'sources' =>
        array (
          'image/jpeg' =>
          array (
            'file' => 'pie-e1650306573387-1024x870.jpg',
            'filesize' => 78674,
          ),
          'image/webp' =>
          array (
            'file' => 'pie-e1650306573387-1024x870.webp',
            'filesize' => 33190,
          ),
        ),
      ),
    )
    

    Output of wp post meta get 5 _wp_attachment_backup_sources

    array (
      'full-orig' =>
      array (
        'image/jpeg' =>
        array (
          'file' => 'pie.jpg',
          'filesize' => 121123,
        ),
        'image/webp' =>
        array (
          'file' => 'pie.webp',
          'filesize' => 92266,
        ),
      ),
    )
    

    Here is where the problem lies. Compare backup sizes with backup sources. Backup sizes contains references to the edit made to the image (hash e1650306573387, stored under a random new hash per core behavior). But backup sources doesn't contain any reference to it, meaning that edit is now lost when it comes to our _wp_attachment_backup_sources storage.

  4. changed the title [-]Ensure edited image sources are backed up when making further edits or restore[/-] [+]Ensure edited image sources are backed up when restoring the original image[/+] on Apr 18, 2022
  5. felixarntz commented on Apr 18, 2022

    @felixarntz
    MemberAuthor

    @mitogh I've updated the issue title and description based on my finding above. The bug is still valid, but it only happens when restoring the original.

  6. self-assigned this
    on Apr 23, 2022
  7. removed
    Needs DevAnything that requires development (e.g. a pull request)
    on Apr 23, 2022
  8. mitogh commented on Apr 23, 2022

    @mitogh
    Member

    Here is where the problem lies. Compare backup sizes with backup sources. Backup sizes contains references to the edit made to the image (hash e1650306573387, stored under a random new hash per core behavior). But backup sources doesn't contain any reference to it, meaning that edit is now lost when it comes to our _wp_attachment_backup_sources storage.

    Oh got it this is only on the new meta added by this plugin. Thanks, let me take a look at this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions