Updated: Comment #N

Problem/Motivation

We still have (and would like to convert) usages of drupal_get_hash_salt() in our OO code. This is not ideal, as tests have to do the if(!function_exists('ffdfdf')) hack etc.. We cannot just use the setting directly as we need to keep the logic that throws an exception if it is empty.

Proposed resolution

Find a new home for this. We could just check for this when we get the hash_salt setting. I think it makes more sense to just have this living somewhere though.

Remaining tasks

Find a place, patch. Convert remaining usages.

User interface changes

None

API changes

Hopefully no more drupal_get_hash_salt(), just the new thing.

https://drupal.org/node/2197037 will need to be updated.

Comments

damiankloip’s picture

Status: Active » Needs review
StatusFileSize
new3.17 KB

After briefly speaking to sun on IRC, he suggested adding a method to Settings itself. The thought had crossed my mind, so this is some good validation.

So, how about this? Haven't converted the remaining usages, or marked drupal_get_hash_salt() as deprecated yet.

xano’s picture

StatusFileSize
new3.48 KB
new1.53 KB

I fixed some docs in the test.

I also think this may not be the right place, or at least not for the code in its current form, as Settings is a component and should therefore be useful and make sense outside the context of Drupal. Adding a method for a very specific setting is questionable, but referring to Drupal-specific use cases (settings.php) is not helpful to outsiders at all.

Wasn't @sun working on a site service? Maybe this would fit in there.

dawehner’s picture

StatusFileSize
new3.84 KB
new944 bytes

Moar changes.

tstoeckler’s picture

Sorry, but I don't really see how we can add that code given that Settings currently lives in Component. What we could do is pass a list of required properties in __construct() and have Settings::get() throw an exception in case a required property is missing. That would make it generic enough for people to re-use outside of Drupal.

tstoeckler’s picture

Actually that would be kind of pointless as well, as you obviously know all of the settings' keys when calling Settings::__construct(), so making Settings throw an exception on a missing key would be weird.

Instead we should throw an exception as soon as we initialize Settings if 'hash_salt' is missing.

sun’s picture

  1. Settings is completely misplaced in Component — it's a 100% Drupalism and we need to move that into Core ASAP. My plan was to move it into Drupal\Core\Site\Settings, which is also where the new Site singleton will be located, because Settings are always loaded from a particular site directory.

  2. Adding dedicated methods for settings that are required to exist makes perfect sense to me. We should consider to add more of them later on. This approach would allow us to "namespace" settings in settings.php and provide dedicated methods to retrieve them, automatically applying defaults; e.g., Settings::getTwig(), etc.

In short, the proposed patch looks good and makes sense to me.

The only part that I don't like is that the method is not static — but to change that, we first have to convert Settings into a proper singleton, because the current code and usage is a total mess. Pretty much following the code of the new Site singleton in #1757536: Move settings.php to /settings directory, fold sites.php into settings.php → this may or may not happen in #2199795: Make the Settings class prevent serialization of actual settings

So for now, the approach of the patch is in line with the current "architecture" of the Settings class, and thus fine.

I'd like to see a few replacements as part of this patch though... At minimum, drupal_get_hash_salt() itself should call the method. :)

damiankloip’s picture

Yeah, this was a quick initial patch tbh :) So yes, it should definitely call the new method!

I agree with you on this, I think this change makes sense, as well as moving Settings into the Core namespace (which I guess is the same reason we agreed when talking about this in IRC yesterday).

dawehner’s picture

I really wonder whether we could special case the logic to initialize the APC classloader.
For all the other usecases it could be worth to try out container parameters for that.

sun’s picture

damiankloip’s picture

I don't think hashSalt() would be suited to a container param tbh - you would then need to inject the container when you needed this. Which seems like it would get pretty strange.

I think we should move on with this patch as-is, now we have the issue sun created in #9 to move Settings into the Core namespace - which I totally agree with.

damiankloip’s picture

StatusFileSize
new4.57 KB
new741 bytes

Here we go, converted the function body to use the new method.

sun’s picture

Status: Needs review » Reviewed & tested by the community

Thanks — looks great to me! :)

ParisLiakos’s picture

Status: Reviewed & tested by the community » Postponed

i feel that this should be postponed to #2208475: Move Settings into Drupal\Core\Site\Settings
if we end up moving it to core, we should actually move it first, and then add this method.
if not, well there are some alternatives posted in #2208475: Move Settings into Drupal\Core\Site\Settings

damiankloip’s picture

This does not make any difference to things in reality (adding this before we move it), as likely this will be so short lived it will be negligible.

We discussed a bit before; people are caught up on Settings actually being a useful component that people might re use...it's not really.

ianthomas_uk’s picture

This approach would still allow people to call settings()->get('hash_salt') without triggering the exception and is confusing DX: How do people know when to call ->getSettingName() and when to call get('setting_name')?

Actually that would be kind of pointless as well, as you obviously know all of the settings' keys when calling Settings::__construct(), so making Settings throw an exception on a missing key would be weird.

Instead we should throw an exception as soon as we initialize Settings if 'hash_salt' is missing.

Erroring on construction is an interesting idea, but it assumes that the setting is required for the site to work at all. That's probably true for hash_salt, as it's required for fundamental things such as form handling, but might not be true in all cases. If we go down this route, we should ensure that it's possible to add an 'error on use' option if we need it in the future.

ianthomas_uk’s picture

Issue summary: View changes
ParisLiakos’s picture

Status: Postponed » Needs work

we can move on here now

damiankloip’s picture

Status: Needs work » Needs review
StatusFileSize
new3.79 KB

Reroll, and made new method static instead. Also, what happened to the Settings class. We seem to have methods doing the same thing that maybe aren't needed? I'm looking at you #2219009: Improve DX of Settings class.

ParisLiakos’s picture

yes indeed we have duplicate methods..the only difference is the fact of being static..
so there are two paths
Settings::get()
and
$this->settings->getSetting()

I find it very confusing tbh..I believe that (i didnt test it) $this->settings->get() would be the exact same thing of calling $this->settings->getSetting()

+++ b/core/lib/Drupal/Core/Site/Settings.php
@@ -70,6 +70,26 @@ public static function getAll() {
+    $hash_salt = static::$instance->get('hash_salt');

hmm the whole other class uses self:: and i think it makes sense because this class is final ( :( )
But anyway lets keep the consistency and use self here too

sun’s picture

Just a silly thought: (to be ignored)

One potential way to address that concern would be:

  public function __call($name, $args) {
    // Check whether the method exists literally.
    if (method_exists($this, $name)) {
      return $this->$name($args[0]);
    }
    // Check whether the method name maps to a setting.
    elseif (isset($this->storage[$setting = substr(Container::underscore($name), 3)])) {
      return $this->storage[$setting];
    }
    // Otherwise, fall back to a literal get().
    else {
      return $this->get(substr($name, 3));
    }
  }

Dunno why I'm posting this, but yeah, the idea is flawed, so please ignore this, unless you can make something more fruitful out of it :-)

damiankloip’s picture

@ParisLiakos, yes, I mean this: #2250491: Remove duplicate methods from Settings class. Seems we could clean that class up considerably. Not sure why #2219009: Improve DX of Settings class got committed with those changes tbh. Is adding duplicate methods better DX? No :)

@sun, I see where you're coming from. I think this could be worth more discussion. However, I think how we have the current patch is sufficient for our needs. The most important thing is our code in core uses this so the exception is thrown. If a developer uses get('hash_salt') or getAll() (could need to dynamically get values etc.. ?) then why not?

damiankloip’s picture

StatusFileSize
new7.59 KB
new3.79 KB

Now with conversion to use this in CsrfTokenGenerator too.

Status: Needs review » Needs work

The last submitted patch, 22: 2207585-22.patch, failed testing.

damiankloip’s picture

Status: Needs work » Needs review
StatusFileSize
new8.08 KB
new502 bytes

Whoops.

ParisLiakos’s picture

looks good to good, besides one thing which i also mentioned in #19

+++ b/core/lib/Drupal/Core/Site/Settings.php
@@ -70,6 +70,26 @@ public static function getAll() {
+    $hash_salt = static::$instance->get('hash_salt');

hmm the whole other class uses self:: and i think it makes sense because this class is final ( :( )
But anyway lets keep the consistency and use self here too

damiankloip’s picture

StatusFileSize
new8.08 KB
new630 bytes

Sorry Paris, I thought I changed that in the last patch but obv. forgot!

ParisLiakos’s picture

Status: Needs review » Reviewed & tested by the community

no problem:) thanks for your patience!

sun’s picture

Hm. I assume/fear that the injected Settings will be serialized much more often with this change, since the CsrfTokenManager gets injected into every form...

#2199795: Make the Settings class prevent serialization of actual settings

It looks like #2201919: Replace drupal_get_hash_salt() with direct Settings call in CsrfTokenGenerator was merged into this issue?

Wondering whether it is necessary to perform that change here? Can we make the constructor call Settings::getHashSalt() instead?

The problem with serialized settings is that they are typically unserialized in a completely different request/context. settings.php might have been changed, but the unserialized Settings class still holds the former settings.

damiankloip’s picture

Status: Reviewed & tested by the community » Needs review
StatusFileSize
new7.02 KB
new2.78 KB

Yes, this is a good point. Let's go with the simplest solution for now like this? Also, yes, I was going to close #2201919: Replace drupal_get_hash_salt() with direct Settings call in CsrfTokenGenerator. Most of that patch is obsolete now anyway.

sun’s picture

Status: Needs review » Reviewed & tested by the community

Thanks.

That appears to be the only safe/secure approach for now. We'll have to study and investigate this whole situation of serialized settings some more - which could use a critical release-blocking issue, because unserialization and usage of possibly stale/outdated settings is a security issue.

catch’s picture

Status: Reviewed & tested by the community » Needs work

No longer applies.

Also shouldn't we mark drupal_get_hash_salt() deprecated here?

damiankloip’s picture

Status: Needs work » Needs review
StatusFileSize
new7.14 KB
new527 bytes

Yep, I think that's a good shout. Rerolled and added deprecated in doc.

ParisLiakos’s picture

Status: Needs review » Reviewed & tested by the community

  • Commit 9ce5973 on 8.x by catch:
    Issue #2207585 by damiankloip, Xano, dawehner: Find a new OO home for...
catch’s picture

Status: Reviewed & tested by the community » Fixed

Part of me thinks twice about this because it further cements that anything with a dependency on Settings has to stay in \Drupal\Core and can't be a component, however:

1. OOP code should not be calling out to procedural code. If we'd stuck to that rule I think we'd have saved ourselves quite a lot of pain this release cycle with hidden dependencies.

2. Like the Cache system, the settings dependency can always be restricted to a factory, then only the factory has to be in \Drupal\Core not the entire subsystem.

Committed/pushed to 8.x, thanks!

Status: Fixed » Closed (fixed)

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