Skip to content

[4.x]: Updating Assets via GraphQL does not trigger EVENT_AFTER_REPLACE_ASSET #17005

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
krafttoast opened this issue Apr 1, 2025 · 6 comments

Comments

@krafttoast
Copy link

krafttoast commented Apr 1, 2025

What happened?

Description

When updating an asset via GraphQL the EVENT_AFTER_REPLACE_ASSET is not triggered.

Steps to reproduce

  1. Upload an asset to Craft

  2. Create a module with the EVENT_AFTER_REPLACE_ASSET and just throw an Error
    Event::on( Assets::class, Assets::EVENT_AFTER_REPLACE_ASSET, function (ReplaceAssetEvent $event) { throw new Error('Some Errormsg'); } );

  3. Create a mutation with payload that replaces the Asset

mutation AssetMutation( $id: ID, $folderId: ID, $document: FileInput, $title: String, ) { save_images_Asset( _file: $document, title: $title, id: $id newFolderId: $folderId ) { id folderId title } }

Payload is the output of the following php fun

public function assetPayload(string $fileData, array $image): String { $payload = [ 'id' => $image['id'], 'folderId' => $image['folderId'], 'title' => $image['name']', 'document' => [ 'filename' => $image['name'], 'fileData' => "data:image/jpg;base64," . $fileData ], ]; return json_encode($payload); }

  1. Replace an Asset via Crafts native backend and observe an error is thrown

  2. Run the mutation for the same Asset and see no Error is thrown

Expected behavior

When updating an Asset via GraphQL the EVENT_AFTER_REPLACE_ASSET and EVENT_BEFORE_REPLACE_ASSET are triggered.

Actual behavior

Said events are not triggered.

Craft CMS version

Craft CMS 4.14.11 Pro

PHP version

PHP 8.2.22

Operating system and version

Linux 6.8.0-56-generic

Database type and version

PostgreSQL 12.14

Image driver and version

Imagick 3.7.0 (ImageMagick 6.9.11-60)

Installed plugins and versions

No response

@i-just
Copy link
Contributor

i-just commented Apr 2, 2025

Hi, thanks for reaching out!

The mutation that’s used to replace a file is actually a saveElement method underneath, not a separate, replace, one, which means the Element::EVENT_BEFORE_SAVE and Element::EVENT_AFTER_SAVE are triggered (as well as Elements::EVENT_BEFORE_SAVE_ELEMENT and Elements::EVENT_BEFORE_SAVE_ELEMENT).

That said, you could still detect if the file is being replaced based on the asset’s scenario. If the data passed to the mutation has the file info and an ID was provided, the scenario will be set to ‘replace’.

I hope this helps!

I’ll close this now, but feel free to reply if you run into any further issues.

@i-just i-just closed this as completed Apr 2, 2025
@aelvan
Copy link

aelvan commented Apr 2, 2025

Hi Iwona,

This is related to an issue they're seeing with my plugin, where I use Assets::EVENT_AFTER_REPLACE_ASSET to remove stale transforms when an asset file is replaced.

But based on what you're saying, I should be using Element::EVENT_AFTER_SAVE instead and check the element type and scenario? What's the purpose of Assets::EVENT_AFTER_REPLACE_ASSET then, when is it triggered and what are the practical differences of changing it? Or do I need to listen to both?

@hiasl
Copy link
Contributor

hiasl commented Apr 2, 2025

Without having it verfified in detail we also believe that Blitz Cache has the same problem (it suffers from the missing event).

And my opinion about closing this: It should not make a difference, if the image gets replaced via GUI or GraphQL. The event should be fired.

@i-just
Copy link
Contributor

i-just commented Apr 3, 2025

@aelvan, the Assets::EVENT_AFTER_REPLACE_ASSET is called from the Assets->replaceAssetFile() method, which also calls Elements->saveElement() and therefore also triggers the Element::EVENT_AFTER_SAVE. So, if the file replacement happens via Assets->replaceAssetFile(), both those events will be triggered. If it happens directly via Elements->saveElement(), only Element::EVENT_AFTER_SAVE will.

That said, we would like to talk about it more internally. I’ll post a reply once we had a chance to do so!

@i-just
Copy link
Contributor

i-just commented Apr 8, 2025

Thanks all for your patience on this one! We discussed this internally and decided to trigger the EVENT_BEFORE_REPLACE_ASSET and EVENT_AFTER_REPLACE_ASSET events via GQL, too - it makes sense to keep things consistent. A PR has been raised and merged.

@i-just i-just reopened this Apr 8, 2025
@brandonkelly
Copy link
Member

Craft 4.14.14 and 5.6.16 are out with that change 🎉

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

No branches or pull requests

5 participants