craftcms / cms

Build bespoke content experiences with Craft.
https://craftcms.com
Other
3.28k stars 635 forks source link

[4.x]: Changing the handle of an asset filesystem breaks asset fields until volumes are updated / resaved #10885

Closed tomdavies closed 2 years ago

tomdavies commented 2 years ago

What happened?

Description

As of Beta 4, changing the handle of a local or remote (S3 tested) Filesystem breaks asset fields that use volumes that use that filesystem.

This is because the volumes table references fs by handle, and this is not updated when a fs is saved/changed.

Steps to reproduce

  1. Create:
    • An asset volume + filesystem (in my case we are using the S3 plugin)
    • A field that uses that asset volume
  2. Change the handle of the fs
  3. Visit the edit field view for the field: A PHP error is shown, referencing the old fs handle
  4. Visit the volume edit view: association to the fs is no longer present
  5. Reselecting the FS in the volume edit view and saving the volume fixes the issue

FWIW this is with an upgraded C3 site using project config, not tested with a clean C4 install.

Expected behavior

I can change the handle of a File System without issue:

Actual behavior

An Error occurred while handling another error:
yii\base\InvalidConfigException: Invalid filesystem handle: s3ClientUploads in /app/vendor/craftcms/cms/src/models/Volume.php:219
Stack trace:
#0 /app/vendor/craftcms/cms/src/elements/Asset.php(576): craft\models\Volume->getFs()
#1 /app/vendor/craftcms/cms/src/elements/Asset.php(558): craft\elements\Asset::_assembleSourceInfoForFolder(Object(craft\models\VolumeFolder), false, Object(craft\elements\User))
#2 /app/vendor/craftcms/cms/src/elements/Asset.php(358): craft\elements\Asset::_assembleSourceList(Array, false, Object(craft\elements\User))
#3 /app/vendor/craftcms/cms/src/base/Element.php(780): craft\elements\Asset::defineSources('settings')
#4 /app/vendor/craftcms/cms/src/fields/Assets.php(250): craft\base\Element::sources('settings')
#5 /app/vendor/twig/twig/src/Extension/CoreExtension.php(1607): craft\fields\Assets->getSourceOptions()
#6 /app/vendor/craftcms/cms/src/helpers/Template.php(101): twig_get_attribute(Object(craft\web\twig\Environment), Object(Twig\Source), Object(craft\fields\Assets), 'getSourceOption...', Array, 'method', false, false)
#7 /app/storage/runtime/compiled_templates/32/32df188ac56fe13c4e9aa1161c80ddfbeb8397d114e7ebe03136a5e99e680f48.php(53): craft\helpers\Template::attribute(Object(craft\web\twig\Environment), Object(Twig\Source), Object(craft\fields\Assets), 'getSourceOption...', Array, 'method')
#8 /app/vendor/twig/twig/src/Template.php(394): __TwigTemplate_3758a5c6de01f8921e2d14cfad3204c5ee2cc5050ab9e7084ac1885ff682620c->doDisplay(Array, Array)
#9 /app/vendor/twig/twig/src/Template.php(367): Twig\Template->displayWithErrorHandling(Array, Array)
#10 /app/storage/runtime/compiled_templates/f4/f42e3b435daa5e96326085a9b8dadc2c4c90d74d569f766280c76198002f6ab7.php(54): Twig\Template->display(Array, Array)
#11 /app/vendor/twig/twig/src/Template.php(394): __TwigTemplate_18afb55a40a24f7ce004be8e6dc0c3cc1612945045e0172948d44bec0cb4af60->doDisplay(Array, Array)
#12 /app/vendor/twig/twig/src/Template.php(367): Twig\Template->displayWithErrorHandling(Array, Array)
#13 /app/vendor/twig/twig/src/Template.php(379): Twig\Template->display(Array)
#14 /app/vendor/twig/twig/src/TemplateWrapper.php(40): Twig\Template->render(Array, Array)
#15 /app/vendor/twig/twig/src/Environment.php(277): Twig\TemplateWrapper->render(Array)
#16 /app/vendor/craftcms/cms/src/web/View.php(389): Twig\Environment->render('_components/fie...', Array)
#17 /app/vendor/craftcms/cms/src/fields/BaseRelationField.php(306): craft\web\View->renderTemplate('_components/fie...', Array)
#18 /app/vendor/twig/twig/src/Extension/CoreExtension.php(1607): craft\fields\BaseRelationField->getSettingsHtml()
#19 /app/vendor/craftcms/cms/src/helpers/Template.php(101): twig_get_attribute(Object(craft\web\twig\Environment), Object(Twig\Source), Object(craft\fields\Assets), 'getSettingsHtml', Array, 'method', false, false)
#20 /app/storage/runtime/compiled_templates/18/18a3ec6503fdb0e5d63748c40839cf7bde7917044a1acfe598c105646b4ebdd4.php(46): craft\helpers\Template::attribute(Object(craft\web\twig\Environment), Object(Twig\Source), Object(craft\fields\Assets), 'getSettingsHtml', Array, 'method')
#21 /app/vendor/twig/twig/src/Template.php(394): __TwigTemplate_7856737e98a65834a3da2b7a333fc4b431cbeed08414aec3fc16107ab8ebdd09->doDisplay(Array, Array)
#22 /app/vendor/twig/twig/src/Template.php(367): Twig\Template->displayWithErrorHandling(Array, Array)
#23 /app/storage/runtime/compiled_templates/6f/6f46c99026b25ac37e164a600a56e02673a18ffce1acdc853378cb36f9d71b10.php(257): Twig\Template->display(Array)
#24 /app/vendor/twig/twig/src/Template.php(171): __TwigTemplate_03a2f0678634e13b2c5ffdb3cac9153f414b8841ed40ea8556a89b76f6c4d26c->block_content(Array, Array)
#25 /app/storage/runtime/compiled_templates/e3/e3d06a797a8a2e9c37e4120cf33b1859319e2837f9b6f17fd8d43a9ce77d3dfb.php(561): Twig\Template->displayBlock('content', Array, Array)
#26 /app/vendor/twig/twig/src/Template.php(171): __TwigTemplate_89baa84f82ca6bd13d122b74dea6ac1ab93462441164d70a58aa8f03c2b24378->block_main(Array, Array)
#27 /app/storage/runtime/compiled_templates/e3/e3d06a797a8a2e9c37e4120cf33b1859319e2837f9b6f17fd8d43a9ce77d3dfb.php(353): Twig\Template->displayBlock('main', Array, Array)
#28 /app/vendor/twig/twig/src/Template.php(171): __TwigTemplate_89baa84f82ca6bd13d122b74dea6ac1ab93462441164d70a58aa8f03c2b24378->block_body(Array, Array)
#29 /app/storage/runtime/compiled_templates/c7/c706ecdb658aee219d246b28ba91578dbe6b7addd4a170dda3c4155333aaea9c.php(96): Twig\Template->displayBlock('body', Array, Array)
#30 /app/vendor/twig/twig/src/Template.php(394): __TwigTemplate_76802370b556bd048326aaeb2de3642b1c6e447797e0c6787eff74ec0de25196->doDisplay(Array, Array)
#31 /app/vendor/twig/twig/src/Template.php(367): Twig\Template->displayWithErrorHandling(Array, Array)
#32 /app/storage/runtime/compiled_templates/50/5061eb366443ea0dd715301b87242c71c28c8f6fe181279e80e5bfd5c535c699.php(56): Twig\Template->display(Array, Array)
#33 /app/vendor/twig/twig/src/Template.php(394): __TwigTemplate_b09d2c35a812e3a3d3f75382f8ac2f630293c28e8470ebb23c314a42a5998b6e->doDisplay(Array, Array)
#34 /app/vendor/twig/twig/src/Template.php(367): Twig\Template->displayWithErrorHandling(Array, Array)
#35 /app/storage/runtime/compiled_templates/e3/e3d06a797a8a2e9c37e4120cf33b1859319e2837f9b6f17fd8d43a9ce77d3dfb.php(172): Twig\Template->display(Array, Array)
#36 /app/vendor/twig/twig/src/Template.php(394): __TwigTemplate_89baa84f82ca6bd13d122b74dea6ac1ab93462441164d70a58aa8f03c2b24378->doDisplay(Array, Array)
#37 /app/vendor/twig/twig/src/Template.php(367): Twig\Template->displayWithErrorHandling(Array, Array)
#38 /app/storage/runtime/compiled_templates/6f/6f46c99026b25ac37e164a600a56e02673a18ffce1acdc853378cb36f9d71b10.php(114): Twig\Template->display(Array, Array)
#39 /app/vendor/twig/twig/src/Template.php(394): __TwigTemplate_03a2f0678634e13b2c5ffdb3cac9153f414b8841ed40ea8556a89b76f6c4d26c->doDisplay(Array, Array)
#40 /app/vendor/twig/twig/src/Template.php(367): Twig\Template->displayWithErrorHandling(Array, Array)
#41 /app/vendor/twig/twig/src/Template.php(379): Twig\Template->display(Array)
#42 /app/vendor/twig/twig/src/TemplateWrapper.php(40): Twig\Template->render(Array, Array)
#43 /app/vendor/twig/twig/src/Environment.php(277): Twig\TemplateWrapper->render(Array)
#44 /app/vendor/craftcms/cms/src/web/View.php(389): Twig\Environment->render('settings/fields...', Array)
#45 /app/vendor/craftcms/cms/src/web/View.php(442): craft\web\View->renderTemplate('settings/fields...', Array)
#46 /app/vendor/craftcms/cms/src/web/TemplateResponseFormatter.php(52): craft\web\View->renderPageTemplate('settings/fields...', Array, 'cp')
#47 /app/vendor/yiisoft/yii2/web/Response.php(1095): craft\web\TemplateResponseFormatter->format(Object(craft\web\Response))
#48 /app/vendor/craftcms/cms/src/web/Response.php(275): yii\web\Response->prepare()
#49 /app/vendor/yiisoft/yii2/web/Response.php(339): craft\web\Response->prepare()
#50 /app/vendor/yiisoft/yii2/web/ErrorHandler.php(136): yii\web\Response->send()
#51 /app/vendor/craftcms/cms/src/web/ErrorHandler.php(185): yii\web\ErrorHandler->renderException(Object(yii\base\InvalidConfigException))
#52 /app/vendor/yiisoft/yii2/base/ErrorHandler.php(135): craft\web\ErrorHandler->renderException(Object(yii\base\InvalidConfigException))
#53 /app/vendor/craftcms/cms/src/web/ErrorHandler.php(64): yii\base\ErrorHandler->handleException(Object(yii\base\InvalidConfigException))
#54 [internal function]: craft\web\ErrorHandler->handleException(Object(yii\base\InvalidConfigException))
#55 {main}

Craft CMS version

4.0.0-beta.4

PHP version

8.0.16

Operating system and version

nitro

Database type and version

mysql 8

Image driver and version

No response

Installed plugins and versions

"craftcms/aws-s3": "^2.0.0-beta.2", "craftcms/redactor": "3.0.0-beta.1", "nystudio107/craft-seomatic": "^4.0.0-beta.6", "verbb/super-table": "^3.0.0-beta.3",

brandonkelly commented 2 years ago

This is sortof by design because volumes are only loosely coupled to their filesystems – we are expecting it will be common to actually set the Asset Filesystem setting to an environment variable, so the filesystem may vary from environment to environment (e.g. a Local FS on dev, and an S3 FS on production).

So as of the next release, Craft will start updating volumes’ Filesystem settings when an FS handle changes, but only for volumes where the FS handle was hardcoded, as opposed to referenced via an environment variable.

tomdavies commented 2 years ago

👍 makes sense

brandonkelly commented 2 years ago

Craft 4.0.0-RC1 is out now with this change.