-
Notifications
You must be signed in to change notification settings - Fork 641
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
[4.x]: Asset::EVENT_DEFINE_URL doesn't give plugins a chance to define the URL #13018
Comments
+1. My plugin Imgixer also uses this event. |
The event was moved to after the built-in URL generation in 4.3 via #12168, to be consistent with how
Not true – Lines 1834 to 1837 in 4adcbee
(That condition was even added to work around an ImageOptimize issue introduced in 4.3.0 – 3f00b8d.) Is the issue here just that there’s doubled efforts, or is something actually broken in 4.4? |
Just saw nystudio107/craft-imageoptimize#373. I suspect that is related to 303e5dd, where Craft is more assertive about generating control panel thumbnails, even for volumes that don’t support transforms directly. I don’t want to revert that, and I don’t want to swap the order of the event/core URL generation for reasons stated. We could add a new ImageOptimize and Imgixer could then start doing this, without needing to bump their use craft\elements\Asset;
use craft\events\DefineUrlEvent;
use yii\base\Event;
$eventName = defined('craft\elements\Asset::EVENT_BEFORE_DEFINE_URL')
? Asset::EVENT_BEFORE_DEFINE_URL
: Asset::EVENT_DEFINE_URL;
Event::on(Asset::class, $eventName, function(DefineUrlEvent $event) {
$event->url = '...';
}); Seem reasonable? |
I agree with you @brandonkelly that the event lets the plugin override Seems like the fix would be for the plugin to also listen to the |
@andersaloof Yeah got it. I think adding the new |
|
Craft 4.4.6 is out now with that event 🎉 |
So unfortunately, I just now was able to sit down and look at this... and it's not going to work for what ImageOptimize needs. You're doing this for the BEFORE event: $event = new DefineUrlEvent();
$this->trigger(self::EVENT_BEFORE_DEFINE_URL, $event);
$url = $event->url; ...while doing this for the existing event: $event = new DefineAssetUrlEvent([
'url' => $url,
'transform' => $transform,
'asset' => $this,
]);
$this->trigger(self::EVENT_DEFINE_URL, $event); So I suspect the same will be the case for @croxton 's plugin as well. |
Sorry, overlooked that. Adjusted for the next release (2c5291f) – as of 4.4.7, If your code is relying on use craft\elements\Asset;
use craft\events\DefineAssetUrlEvent;
use yii\base\Event;
if (
defined('craft\elements\Asset::EVENT_BEFORE_DEFINE_URL') &&
(new ReflectionClassConstant(Asset::class, 'EVENT_BEFORE_DEFINE_URL'))->getDeclaringClass()->name === Asset::class
) {
$eventName = Asset::EVENT_BEFORE_DEFINE_URL;
} else {
$eventName = Asset::EVENT_DEFINE_URL;
}
Event::on(Asset::class, $eventName, function(DefineAssetUrlEvent $event) {
$event->url = '...';
}); We have to use reflection because |
…sform work even when using an external service to do the transforms ([#373](#373)) ([#13018](craftcms/cms#13018))
Here's what I ended up with, for anyone who stumbles across this: // Use Asset::EVENT_BEFORE_DEFINE_URL if it's available
// ref: https://github.com/craftcms/cms/issues/13018
try {
$ref = new \ReflectionClassConstant(Asset::class, 'EVENT_BEFORE_DEFINE_URL');
} /** @noinspection PhpRedundantCatchClauseInspection */ catch (\ReflectionException) {
$ref = null;
}
$eventName = $ref?->getDeclaringClass()->name === Asset::class
? Asset::EVENT_BEFORE_DEFINE_URL
: Asset::EVENT_DEFINE_URL;
// Handler: Assets::EVENT_DEFINE_URL
Event::on(
Asset::class,
$eventName,
static function (DefineAssetUrlEvent $event): void {
... |
Alright, 4.4.7 is out now with the additional event changes. |
What happened?
Description
ImageOptimize, and potentially other plugins hook into Craft via
Asset::EVENT_DEFINE_URL
to potentially define the URL for an asset coming from an external source.In the past, this worked fine... but some recent change (Craft 4.4 perhaps?) caused this to no longer work as expected, or at least now have unfortunate side-effects because what happens is this:
https://github.com/craftcms/cms/blob/4.4/src/elements/Asset.php#L1824
The call to
$url = $this->_url($transform, $immediately);
ends up causing Craft to start doing its thing, transforming the image either immediately or via Queue job, even though the plugin itself is taking care of everything that needs to be done to define the URL.Contrast this with the
Asset::_url()
method which does this:Which causes the operation to immediately short-circuit and return the URL that the plugin defined via the
Asset::EVENT_BEFORE_GENERATE_TRANSFORM
event.While I could refactor the ImageOptimize code to use
Asset::EVENT_BEFORE_GENERATE_TRANSFORM
instead, it feels like this might be a mistake? The currentAsset::EVENT_DEFINE_URL
event never allows a plugin or module to override whatever Craft is going to do.I think the code should be refactored like this:
...so that it returns immediately if a plugin/module set
$event->url
so the plugin can short-circuit theAsset::EVENT_DEFINE_URL
operation properly as before.Related issues:
nystudio107/craft-imageoptimize#373
Craft CMS version
4.4.5
PHP version
n/a
Operating system and version
n/a
Database type and version
n/a
Image driver and version
n/a
Installed plugins and versions
ImageOptimize 4.0.4
The text was updated successfully, but these errors were encountered: