Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
Problem/Motivation
Follow-up from Add a thumbnail/icon field to Paragraphs type
We can do something like have a file in the module, copy it to public:// and save as a file entity, then reference it. For the demo module, for example (which we can also do later, since we don't actually use the icons yet anyway)
Proposed resolution
Remaining tasks
User interface changes
API changes
Data model changes
Comment | File | Size | Author |
---|---|---|---|
#40 | 2832021-40.patch | 11.52 KB | aimevp |
| |||
#36 | selected_6893.png | 105.22 KB | KondratievaS |
#34 | interdiff-31-34.txt | 3.49 KB | aleevas |
#34 | 2832021-34.patch | 11.46 KB | aleevas |
|
Comments
Comment #2
toncic CreditAttribution: toncic at MD Systems GmbH commentedComment #3
miro_dietikerOr we could keep it in the module static location and use that as a fallback.
And use the UUID based reference that user can use through the UI as an override to it.
Then, import doesn't need to process anything at all.
Comment #4
miro_dietikerComment #5
miro_dietikerComment #6
toncic CreditAttribution: toncic at MD Systems GmbH commentedComment on wrong issue. Sorry.
Comment #7
miro_dietikerHm, reverting relation changes...
Comment #8
toncic CreditAttribution: toncic at MD Systems GmbH commentedComment #9
toncic CreditAttribution: toncic at MD Systems GmbH commentedComment #10
miro_dietikerThe title is misleading. This is not a default icon that is a global fallback.
This is about an icon that is shipped as a default by a module if the paragraph type is imported as configuration.
Comment #11
BerdirRight. That said, a default icon ison (issue) is something we need as well I think? But that part is easy.
Also confused about your #3, which does seem to be about a default icon.
Also not sure what you need from me, I already provided two possible ways to do this, one would code based to copy the files, the other approach is to use default_config, but that also needs file_entity or https://www.drupal.org/project/better_normalizers.
Comment #12
miro_dietikerYeah, technically, #3 is a "default icon", but some that is limited to a specific paragraph type.
I understood the "default icon" as a super global icon fallback, that doesn't make sense. If a specific paragraph has no icon, we just don't show any icon. But i'm open to have a config path based default fallback icon that simply points to a file (and could be overridden by the user).
Since i'm strongly against adding dependencies to make the icons work, we have two options left:
- My per-Paragraph-Type config path that is technically a per-paragraph default icon
- Your copy on install
Prior to implementation, we still need a decision. :-)
Comment #13
BerdirI'm not sure how a string based approach would work, how would the generic code know that the icon for paragraph demo text + image is in paragraphs_demo module, for example? or in the new paragraphs_something experimental thing that we're currently discussing? Without the per-module stream wrappers which are still not in core (which would result in module://paragraphs_demo/icons/text_image.png, which would be very technical).
It would either need to be relative to public files directory, so we still have to copy, or absolute, but then we need to hardcode the path to the module (at install, and moving it would break it)
Comment #14
seanBAfter running in to this we have posted some thoughts to solve this in #2830016: Add a thumbnail/icon field to Paragraphs type.
Comment #15
dubcanada CreditAttribution: dubcanada commentedIt would be nice if you could do something like
Or something. I don't see any reason we would need to accept binary images. We could just limit it to SVG and allow either people to upload them (in which cause you would use icon_uuid and file system) or paste the SVG code somewhere.
Comment #16
manuel.adanHere we have a situation of dependency on content from the configuration. It is similar to the "broken block effect", which occurs with instances of missing custom blocks (see #2918149: "This block is broken or missing..." should only be shown to users that have access to do something about it). This ends in an inconsistency that should be solved in some way.
One approach to solve this is to store in configuration a default content (serialized) to be used when the referenced content is missing. The content is recreated automatically from the default value when required (on demand). That's what I did in the fixed block content module, that solves the broken block effect.
With this patch, a new property is added to the paragraph type that stores the default icon, encoded in Base64 under the data URL scheme (RFC 2397). Everything works transparently, the default icon value is updated when the paragraph type is saved and the file icon is recreated if not found (it was deleted or it is a new environment).
The patch also creates the paragraphs icon location (public://paragraphs_type_icon/) if not present, as in new environments.
The URL scheme also opens the door to a new approach without any dependency on files. This format can be embed in CSS background images and in HTML "img" tags.
Note that, due to limitations of converting MIME to file extension, the patch works safely only with the supported icon types: JPG, PNG or SVG.
Comment #18
manuel.adanFailed tests do not seem to be related to the last patch.
Comment #19
BerdirI wouldn't be so sure about that, daily tests are passing just fine: https://www.drupal.org/node/2130961/qa
Comment #20
miro_dietikerI really don't like patterns where a getter implicitly triggers a save due to some magic functionality.
Again, can we not simply just do this on config import only?
Either set this only if the icon changed on save or maybe only on config export. This now slows down all config saves.
Comment #21
manuel.adanTests failed because I forget the calling to parent::preSave when presaving, so dependencies wasn't calculated. In addressing this, I found that the calculateDependencies() method currently returns the dependencies, when it must returns the object itself. I opened a new issue for that (#2967635: Paragraphs type calculateDependencies returns wrong value).
However, presave is no longer needed since the default icon value is now set when and where the UUID currently does, that is, in the paragraphs type form. That solves some unnecessary processing when the type is saved, as pointed by Miro. Perhaps a new "setIcon" method could a be better way, but it implies an API change.
I do not like to do something else than read on getters too, but by its nature, content entities are dynamic and they can be updated or deleted in the runtime, so the icon file could be missing not only when importing configuration in a new environment. At the moment, I do not have a better solution than check that the required content exists when it is needed.
Storing and serving the icon data as an embed image rather than a file would solve this and some other weakness around the current implementation, but it is something to evaluate out of this issue.
Comment #22
jwaxo CreditAttribution: jwaxo at Phase2 commentedThis patch no longer succeeds since 8.x-1.3. I've updated the diff to apply properly and re-uploaded.
Comment #23
hanoiiAm I understanding right that this issue is just for config provided by a module?
Is there a proper way or thought about how to "deploy" an icon that I uploaded to my local so that it can be pushed, with the image, to the repo or something like that?
I notice an uuid is exported, but what's the use of that? This is probably a general problem, but any current recommended workaround?
Thanks!
Comment #24
manuel.adan@hanoii, from my point of view, the right way to add an icon file is by adding it to the site assets. Icons are not really pieces of content, so shouldn't be managed as so. Drupal core does it in this way. As an example, the core shortcut module provides some icons at core/modules/shortcut/images, then it makes use of them as a background images at core/modules/shortcut/css/shortcut.icons.theme.css
This issue attempts to solve the use of content that should be part of config or file assets. IMHO, we should turn this into a new issue to make paragraphs to manage their icons as the core does.
Comment #25
Berdirshortcut isn't using icons for user-created configuration, so that can't be compared.
What can be compared is block config/content entities, which is actually (not) working just like this in core as well.
The only option is similar to what the patch is doing, exporting the raw data in the config. However, I think it would be better to do that specifically during config import/export and not on any save operation. Similar to \Drupal\field\FieldStorageConfigStorage::mapFromStorageRecords()
Comment #26
manuel.adanSystem icon files, like the mentioned shortcut icon:
Paragraphs icons:
Currently, paragraphs type icons are set in two locations, a reference in config and the file icon itself as content. So we have a config dependency on content that the patch tries to solve it by moving the icon file content to config.
@hanoii refers to a general strategy to manage situations like this one, and core does it very well: icon file as part of the site assets and reference to it when needed. For site icons, a good place would be "sites/default/assets/icons" or "assets/icons".
Comment #27
manu manuHi,
The patch in #22 does not applies anymore, because tests have been moved in #2753889: Convert ParagraphsTestBase and the easy-to-convert tests extending it to BrowserTestBase
Here is a re-rolled patch.
Comment #29
aleevasUploaded fix for failed test and replaced some deprecated code
Comment #31
aleevasNext patch
Comment #32
aleevasComment #33
a.milkovskyFunctional review: works amazing!
Technical review (some thoughts):
I would assign $icon_file_uri outside of if. It is easy to miss this method call.
What if we re-save the existing file instead of deleting it?
Maybe I am the only one. But for me it is hard to read method calls and nested "ifs" inside the "if" condition.
Comment #34
aleevasAdded some fixes related to comment #33
Comment #35
aleevasComment #36
KondratievaS CreditAttribution: KondratievaS at Skilld commentedIssue is fixed
Comment #37
JeroenT@KondratievaS, I guess the status you mean is RTBC ;-)
Comment #38
BerdirI did not now that data: suppots a media type, that's neat.
I'm not sure when this would be used?
The only call to this method that I can see is when this very call fails, so in which case should it ever go in here?
Comment #39
BerdirMaybe setting/unsetting icon_default should be done in preSave(), to make sure that it never gets out of sync?
Comment #40
aimevpThese patches were working great for us until recently when we tried using it in our install profile (which is using paragraphs and this patch).
It's strange because we've been using patch #22 for quite some time while performing clean installs but only recently we've noticed problems where an icon couldn't be moved from the "temporary" directory to it's destination, which is the icon directory in the files directory. Upon inspection we've noticed the upload directory didn't exist yet when trying to move the icon. This failure however led to an uncompleted installation which made it a big issue for us. We are not sure why this started happening but is it possible something changed in Drupal Core's install procedures which led to these recent failures?
Anyhow, by tinkering a tiny bit with the code in the patch (which modifies "src/Entity/ParagraphsType.php") we've had better results in our initial tests. What we've done is just move the "checking if the upload directory exists ($filesystem->prepareDirectory(...))" before the process of "saving the icon ($filesystem->saveData(...))".
We will test further to be sure. In the meantime please find a rewrite of the patch with our small modification in attachment.
Comment #42
BerdirYes, that change definitely makes sense, the directory needs to be prepared before saving the data for it.
We've tested this in our project too and it seems to work nicely. Still room for improvements, but it's a good first step I think and has tests.
Comment #44
ChristianAdamski CreditAttribution: ChristianAdamski as a volunteer commentedSorry to resurrect the dead, but: how do I use this?
1.) I locally set icons for paragraphs.
2.) I export the config
3.) I push the config to staging system & import
4.) ???
5.) Profit. Icons showing up on stage.
I'm struggling at 4.)
Comment #45
BerdirThere is no step 4. your exported config files should have a long base64 blob in them, that is the icon. if you import that, it should create the file and the icon should be there. Seems to work fine for us.
Comment #46
ChristianAdamski CreditAttribution: ChristianAdamski commentedGot it. Thank you!