Skip to content

Commit

Permalink
Pulls in the changes from #35973 to check whether an image has been d…
Browse files Browse the repository at this point in the history
…eleted from the attachments.

If the image block was not replaced with an embed,  and it's not an external image, and it's been deleted from the database, clear the attributes and trigger the placeholder.
  • Loading branch information
ramonjd committed Jun 3, 2022
1 parent d9e339b commit 320d630
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 0 deletions.
60 changes: 60 additions & 0 deletions packages/block-library/src/image/edit.js
Expand Up @@ -26,6 +26,7 @@ import { image as icon } from '@wordpress/icons';
* Internal dependencies
*/
import Image from './image';
import { isMediaFileDeleted } from './utils';

/**
* Module constants
Expand Down Expand Up @@ -85,6 +86,20 @@ function hasDefaultSize( image, defaultSize ) {
);
}

/**
* Checks if a media attachment object has been "destroyed",
* that is, removed from the media library. The core Media Library
* adds a `destroyed` property to a deleted attachment object in the media collection.
*
* @param {number} id The attachment id.
*
* @return {boolean} Whether the image has been destroyed.
*/
export function isMediaDestroyed( id ) {
const attachment = window?.wp?.media?.attachment( id ) || {};
return attachment.destroyed;
}

export function ImageEdit( {
attributes,
setAttributes,
Expand Down Expand Up @@ -125,6 +140,48 @@ export function ImageEdit( {
return pick( getSettings(), [ 'imageDefaultSize', 'mediaUpload' ] );
}, [] );

// A callback passed to MediaUpload,
// fired when the media modal closes.
function onCloseModal() {
if ( isMediaDestroyed( attributes?.id ) ) {
setAttributes( {
url: undefined,
id: undefined,
} );
}
}

/*
Runs an error callback if the image does not load.
If the error callback is triggered, we infer that that image
has been deleted.
*/
function onImageError( isReplaced = false ) {
noticeOperations.removeAllNotices();
noticeOperations.createErrorNotice(
sprintf(
/* translators: %s url or missing image */
__( 'Error loading image: %s' ),
url
)
);

// If the image block was not replaced with an embed,
// and it's not an external image,
// and it's been deleted from the database,
// clear the attributes and trigger the placeholder.
if ( id && ! isReplaced && ! isExternalImage( id, url ) ) {
isMediaFileDeleted( id ).then( ( isFileDeleted ) => {
if ( isFileDeleted ) {
setAttributes( {
url: undefined,
id: undefined,
} );
}
} );
}
}

function onUploadError( message ) {
noticeOperations.removeAllNotices();
noticeOperations.createErrorNotice( message );
Expand Down Expand Up @@ -323,6 +380,8 @@ export function ImageEdit( {
containerRef={ ref }
context={ context }
clientId={ clientId }
onCloseModal={ onCloseModal }
onImageLoadError={ onImageError }
/>
) }
{ ! url && (
Expand All @@ -339,6 +398,7 @@ export function ImageEdit( {
onSelectURL={ onSelectURL }
notices={ noticeUI }
onError={ onUploadError }
onClose={ onCloseModal }
accept="image/*"
allowedTypes={ ALLOWED_MEDIA_TYPES }
value={ { id, src } }
Expand Down
23 changes: 23 additions & 0 deletions packages/block-library/src/image/utils.js
Expand Up @@ -3,6 +3,11 @@
*/
import { isEmpty, each, get } from 'lodash';

/**
* WordPress dependencies
*/
import apiFetch from '@wordpress/api-fetch';

/**
* Internal dependencies
*/
Expand Down Expand Up @@ -72,3 +77,21 @@ export function getImageSizeAttributes( image, size ) {

return {};
}

/**
* Performs a GET request on an image file to confirm whether it has been deleted from the database.
*
* @param {number=} mediaId The id of the image.
* @return {Promise} Media Object Promise.
*/
export async function isMediaFileDeleted( mediaId ) {
try {
const response = await apiFetch( {
path: `/wp/v2/media/${ mediaId }`,
} );
const isMediaFileAvailable = response && response?.id === mediaId;
return ! isMediaFileAvailable;
} catch ( err ) {
return true;
}
}

0 comments on commit 320d630

Please sign in to comment.