ClientConfig: Issues with global values and update events

I’m setting up a template that takes advantage of ClientConfig and multiple chunks to generate a custom css and UI via CSSsweet. The idea is letting the user choose style things like colors and fonts, and structural things like social icons in top bar/footer or hamburger/normal menu.

It all works quite neatly but i’m having issues regarding ClientConfig.

1. Context-Aware mode is sketchy
Example 1: Image field with the logo that goes in the header is called with [[++header_logo]]. If the context field has a value it works, if it’s just the global value it returns a broken image “/”. That happens also with text fields, like company phone, mail.
Example 2: [[++main_color]], this values is parsed with csssweet but only takes the global one, context specific color is totally ignored, but i might be missing something.

Possible workarounds
A- Is there a way to force global values? I don’t know, something like [[++config-setting]] -> defaults to global value and [[++config-setting:context]] -> takes the current context value
B- Maybe a way to disable the global thing alltogether and force users to fill every context separately? (Not optimal i know)
C- Maybe if a context specific field is empty have it replaced by the global value on save? (Good for fallbacks etc)
D- Have context specific groups? So i can have the “Theme Options” tab only on global and the “Company details” tab for every context? (FTW).
A and D would be good additions to ClientConfig imho :slight_smile:

For now to avoid issues i have disabled the context-aware function and everything is working as intended, but it would be helpful to have more flexibility for multisites/multilanguage projects.

2. I have CSSSweet set to update on “ClientConfig_ConfigChange” but it only trigger if i save the configuration twice.
It also works correctly if i manually empty modx cache or save the base chunk for csssweet. But we usually hide all chunks and system elements to the end user so it would be optimal if the config event actually refreshed csssweet as well on the first save.

Do you have a header_logo set as global value?

ClientConfig needs to know what context to use when loading its values. I don’t know how csssweet works, but perhaps that isn’t setting the right context or not at the right time.

This is probably because the config change event is fired when saving the configuration. In the save request, the settings loaded into memory (i.e. [[++header_logo]]) are still old. This would be worth a feature request to make it so that the settings are reloaded before firing the event to simplify third party integrations, or you could look at updating csssweet so it only invalidates the cache and doesn’t create the new one right away.

Do you have a header_logo set as global value?

Yes, but it still loads the current context setting which is empty.

ClientConfig needs to know what context to use when loading its values. I don’t know how csssweet works, but perhaps that isn’t setting the right context or not at the right time.

CSSSweet has a context setting in the plugin properties but even when i tried setting that it defaulted to the global values. Weird.

This is probably because the config change event is fired when saving the configuration. In the save request, the settings loaded into memory (i.e. [[++header_logo]] ) are still old. This would be worth a feature request to make it so that the settings are reloaded before firing the event to simplify third party integrations, or you could look at updating csssweet so it only invalidates the cache and doesn’t create the new one right away.

That makes sense. I’ll try fiddle with the plugin events to see if i can find a better pipeline to trigger the various refreshes.

did you manage? I have the same issue. If I make settings context specific, they alway only display what is in the default context.

Context entries all look correct I checked the DB.

yes, kind of, i had to make a plugin myself to clear the empty values in the database so that it will load the global values instead, it fairly easy, something like this;

     case 'ClientConfig_ConfigChange':
        /* Grab the class */
        $path = $modx->getOption('clientconfig.core_path', null, $modx->getOption('core_path') . 'components/clientconfig/');
        $path .= 'model/clientconfig/';
        $clientConfig = $modx->getService('clientconfig','ClientConfig', $path);

        /* If we got the class (gotta be careful of failed migrations), grab settings and go! */
        if ($clientConfig instanceof ClientConfig) {

		  //check if context aware option is set to true
		  if(!$modx->getOption('clientconfig.context_aware')) return;

		  //get all available context cg system settings from the DB
		  $cgSettings = $modx->getCollection('cgContextValue');

		  //loop through context cg system settings
		  foreach ($cgSettings as $setting) { 
			$settingID = $setting->get('setting');
			$settingValue = $setting->get('value');
			//check for empty values
			if ($settingValue == "") {
				//get rid of them
				$setting->remove();

				$modx->log(modx::LOG_LEVEL_INFO, 'ClearEmptyContextSettings: The empty config setting ' . $settingID . ' => ' . $settingValue . 'has been succesfully cleared.');
			}
	      }

		  //clear modx cache
		  $cacheRefreshOptions =  array( 
			'system_settings' => array(),
			'context_settings' => array()
		  );
		  $modx->cacheManager->refresh($cacheRefreshOptions);

        }

      break;

I just released v1.2 yesterday which ignores empty context-values, allowing those to fallback to the global values instead.