Support from Acquia helps fund testing for Drupal Acquia logo

Comments

jibran created an issue. See original summary.

jibran’s picture

DamienGR’s picture

Thank you jibran, it works.

jibran’s picture

RTBC maybe?

samuel.mortenson’s picture

Would this change mean that the Entity Embed button will not have an icon if the module is installed during config import? We always want an icon to be present for our Entity Embed button, so if there's a specific error we can address instead of skipping the install logic I would prefer that.

jibran’s picture

Would this change mean that the Entity Embed button will not have an icon if the module is installed during config import?

@samuel.mortenson I just verified this on the client staging site and this is correct. I pinged @alexpott about this.

jibran’s picture

Issue summary: View changes
samuel.mortenson’s picture

Ok, with that in mind I think the most complete solution would be to have this check, and have an update hook to be run post-config sync that checks if the icon is added, and if not adds it. Does that make sense?

jibran’s picture

Yeah, that makes sense.

jibran’s picture

We can set some variable in state during hook_install and in post update hook if the variable is set we'll add the icon and unset the the variable.

jibran’s picture

FileSize
1.55 KB

How about this?

alexpott’s picture

+++ b/file_browser.post_update.php
@@ -0,0 +1,21 @@
+function file_browser_post_update_set_file_browser_icon() {

This is run as part of update.php and behaves like hook_update_N(). I think all you need to do is check if the config is syncing. If the incoming going has the module installed then the incoming config should also have the uuid set.

Also the embed.button.file_browser should not fail importing if the file entity is not present - all dependencies on content should be soft and not enforced during import in order to prevent issues like this.

jibran’s picture

This is run as part of update.php and behaves like hook_update_N(). I think all you need to do is check if the config is syncing.

I created the first patch https://www.drupal.org/files/issues/fix-install_0.patch and it was doing the exactly same thing and we ran into #5 because of that.

Also the embed.button.file_browser should not fail importing if the file entity is not present - all dependencies on content should be soft and not enforced during import in order to prevent issues like this.

It imports the config just fine but it $uuid = $file->uuid(); generates error trying to access uuid method on NULL.

samuel.mortenson’s picture

#13 covers it, the icon is not required for the module to function - but is a "nice to have"/soft dependency and as far as I can tell this sort of install routine is the only way to add an icon to an Entity Embed button.

samuel.mortenson’s picture

@jibran Is this missing an include/require/info.yml change? Also, would the file_browser_post_update_set_file_browser_icon hook be run every time an update is ran? I want to provide a default icon on install, but also want users to be able to change that icon if they want to without overriding it later on.

jibran’s picture

Is this missing an include/require/info.yml change?

No patch is complete.

Also, would the file_browser_post_update_set_file_browser_icon hook be run every time an update is ran?

No it'll just run once.

I want to provide a default icon on install, but also want users to be able to change that icon if they want to without overriding it later on.

This is not run on install now. After the install you have to run update.php to setup the icon.

alexpott’s picture

Status: Needs review » Needs work

The current patch is not right... all you need to do is this:

 /**
 * Implements hook_install().
 */
function file_browser_install() {
  // Add an icon for File Browser.
  $data = file_get_contents(dirname(__FILE__) . '/file_browser_icon.png');
  $file = file_save_data($data, 'public://file_browser_icon.png', FILE_EXISTS_REPLACE);

  if (!\Drupal::isConfigSyncing()) {
    // Update our configuration to use the icon.
    $uuid = $file->uuid();
    $configuration = \Drupal::configFactory()->getEditable('embed.button.file_browser');
    $configuration->set('icon_uuid', $uuid);
    $configuration->save();
  }
}

We need to add documentation to hook_install about the dangers of doing programatic configuration updates and not checking this.

alexpott’s picture

The solution in #11 will not work because if the post update exists at install time it will never run - exactly the same as hook_update_N

jibran’s picture

Status: Needs work » Needs review
FileSize
935 bytes

The solution in #11 will not work because if the post update exists at install time it will never run - exactly the same as hook_update_N

Yes, you are correct. Thank you @alexpott for explaining it.
It means there is no solution for #5?

samuel.mortenson’s picture

We could have a one-time update (normal hook_update_N) that checks if an icon is set and if not sets it, in addition to this change. That would cover legacy users without icons as well as people that run into this issue.

jibran’s picture

I think we don't have to worry about #5 anymore. I thought about it and here is how #5 is not a problem.
- During development you enable the module.
- The config is updated on install.
- You export the config.
- You commit your changes and deploy your code on staging site.
- During the deploy you import all the config.
- During config import file_browser is installed.
- And in the imported config the icon is already set.
- During module installation file_browser_install is called.
- We copy the file again generate the new uuid but config has the old uuid.
- !\Drupal::isConfigSyncing() stops the config update.
- Because the config has the old uuid that is why staging site was not showing the icon.
- We have to change the uuid either in DB or in config to solve the problem.

We could have a one-time update (normal hook_update_N) that checks if an icon is set and if not sets it, in addition to this change. That would cover legacy users without icons as well as people that run into this issue.

As @alexpott said all the update hook and post update hook are not run at the module installation and the DB scheme of the module is set to the latest N present in install file.

alexpott’s picture

@jibran - #5 is irrelevant and misleading - if the module is being installed during a config import then it must have been installed on a site somewhere not as part of a part config import. So the config change will have occurred. If this is not the case then you have hacked your config and everything is on your head at that point.

alexpott’s picture

However, it might be worth considering creating the file here with a fixed UUID. That way icon won't go missing after a config import.

alexpott’s picture

The other way of fixing this is way more complicated and I'm not sure will work very well. Basically only creating the file if not installing and then adding an event subscriber to the missing content entity event in the config importer and creating the file as necessary. But you're never going to know that you are creating the right file.

So fixing the UUID seems like a good compromise.

jibran’s picture

So the config change will have occurred.

I agree and totally understand this now but when the module is installed during config import then we'll get a new uuid. Isn't this right according to the patch in #19? And the config will have the old uuid which was generated at the time of first install.

alexpott’s picture

Re #25 see #23 and #24 :)

jibran’s picture

Thank you for #24 it is much clear now.

jibran’s picture

Title: Fix the module install » Fix the module install during config export
FileSize
1.23 KB

@alexpott how about this? I don't know if changing the uuid is like this is a good practice.

jibran’s picture

Title: Fix the module install during config export » Fix the module install during config import
heddn’s picture

Status: Needs review » Reviewed & tested by the community

#28 fixed the problem for me.

alexpott’s picture

Just set the UUID of the file to a known value when you create the file. Imo this is okay. It is the same file. It's simpler with way less logic and messing about.

jibran’s picture

Status: Reviewed & tested by the community » Needs review
FileSize
1.25 KB

Thanks @heddn for testing it.

Just set the UUID of the file to a known value when you create the file. Imo this is okay. It is the same file. It's simpler with way less logic and messing about.

@alexpott I just wanted to check my approach with you. You are absolutely right about simplicity. Here is the updated patch and thank you for all your help.

jibran’s picture

samuel.mortenson’s picture

Status: Needs review » Fixed

Looks good in my manual testing, thanks @jibran et. all!

heddn’s picture

#32 definitely doesn't solve the problem. Re-open or open a new issue?

Somewhere in ConfigInstaller->installDefaultConfig(), the default config isn't installed.

!$this->isSyncing() on ~ line 101 seems to part of the culprit.

samuel.mortenson’s picture

@heddn We should re-open this issue since this was committed so recently, do you have steps to reproduce so that I can replicate what you're seeing locally?

heddn’s picture

Status: Fixed » Needs work
FileSize
1.23 KB

For now, so I can keep moving, here's a patch to revert back to #28. I don't think it is the solution.

It is simple to reproduce. Try install using config_installer profile and already have config setup for file_browser. By the time the hook_install is run, the default config isn't imported so it throws a PDO exception because the retrieval of the UUID returns a NULL.

heddn’s picture

heddn’s picture

heddn’s picture

alexpott’s picture

@heddn it needed an upgrade path to set the uuid of the file and config to the default value and then everything should work.

Also tests.

heddn’s picture

re:42, an update, as in a post install update?

alexpott’s picture

Yes

heddn’s picture

Here we go. Let's go with hard-coding the UUID. The config isn't always available during the installation. To test this, I had to install the site using config_installer profile with an already provided config for the UUID.

alexpott’s picture

@heddn actually we could use the ExtensionInstallStorage to read the default config...

jibran’s picture

FileSize
1.07 KB

Here you go post update function.

heddn’s picture

Working on a combined patch to include #47, #46 & #45

heddn’s picture

Interdiff is of the changes introduced to respond to #46.

jibran’s picture

+++ b/file_browser.install
@@ -10,13 +10,12 @@
-  $configuration = \Drupal::configFactory()->get('embed.button.file_browser');
-  $uuid = $configuration->get('icon_uuid');
...
+  $uuid = \Drupal::service('config.storage.sync')->read('embed.button.file_browser')['icon_uuid'];

@alexpott do we really need that?

heddn’s picture

@jibran, you do need it if you are using config_installer install profile. If you don't have it, the site installation fail 100% of the time.

alexpott’s picture

Status: Needs review » Needs work
+++ b/file_browser.install
@@ -10,13 +10,12 @@
+  $uuid = \Drupal::service('config.storage.sync')->read('embed.button.file_browser')['icon_uuid'];

This would only work if you have it in sync storage. I Was trying to say to use ExtensionInstallStorage - with which you can read the default config provided by the module. That is the only thing that is guaranteed to be there.

alexpott’s picture

+++ b/file_browser.post_update.php
@@ -0,0 +1,37 @@
+  $files = \Drupal::entityTypeManager()
+    ->getStorage('file')
+    ->loadByProperties(['uri' => 'public://file_browser_icon.png']);
+  if (!empty($files)) {

How about loading by the current UUID? Should be able to lose this complexity.

jibran’s picture

Status: Needs work » Needs review
FileSize
1.95 KB

Something like this?

alexpott’s picture

Issue tags: +Needs tests
+++ b/file_browser.install
@@ -12,8 +12,10 @@ function file_browser_install() {
+  if ($data = \Drupal::service('config.storage.schema')->read('embed.button.file_browser')) {

You can't use this service - it is reading the schema. You just need to create a new ExtensionInstallStorage... something like:
new \Drupal\Core\Config\ExtensionInstallStorage(\Drupal::service('config.storage'));

jibran’s picture

Sorry, I don't know a lot about ExtensionInstallStorage. Please feel free to update the patch.

heddn’s picture

jibran’s picture

+++ b/file_browser.post_update.php
@@ -0,0 +1,37 @@
+function file_browser_post_update_default_uuid() {

FYI I updated this function in #54. Sorry for not creating interdiff.

pguillard’s picture

Status: Needs review » Reviewed & tested by the community

#57 fixed the missing uuid issue for me.

I do not master the subject, so I wonder if I should set it to RTBC...

samuel.mortenson’s picture

I'm going to attempt to write tests for this before committing.

samuel.mortenson’s picture

Identical patch to #57 with tests this time. If the tests work as expected I'll commit.

samuel.mortenson’s picture

Status: Needs review » Needs work
samuel.mortenson’s picture

Status: Needs work » Needs review

The last submitted patch, 54: fix_the_module_install-2696593-54.patch, failed testing.

The last submitted patch, 57: fix_the_module_install-2696593-57.patch, failed testing.

The last submitted patch, 61: fix_the_module_install-2696593-61-test-only.patch, failed testing.

  • samuel.mortenson committed 785da49 on 8.x-1.x
    Issue #2696593 by heddn, jibran, samuel.mortenson, alexpott, DamienGR,...
samuel.mortenson’s picture

Status: Needs review » Fixed

Committed! Thanks all for the iteration and review. Also, we finally have a test! I'll also be adding Javascript testing as a part of the Media sprints in July.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.