revolution icon indicating copy to clipboard operation
revolution copied to clipboard

Convenience method for saving system settings

Open modxbot opened this issue 14 years ago • 13 comments

everettg_99 created Redmine issue ID 4494

It'd make life much easier for nubes and pros alike if there were a convenience method for updating a system setting.

$modx->getOption('my_setting');

Only gets a cached version, and confusingly, the setOption method does not persist the value beyond the page request.

I'd recommend something as simple to use as WordPress' get_option() and update_option() functions. The MODx equivalent of update_option() might look like this:

/**
 * Convenience function to update or create system settings.
 *
 * @param   string  unique key identifying the system setting to be updated or created
 * @param   string  optional string value
 */
public function getOption($key, $value='') {
    
    $Setting = $this->getObject('modSystemSetting', $key);
    if ( empty($Setting) ) {
        $Setting = $this->newObject('modSystemSetting');
    }
    $Setting->set('value') = $value;
    $is_success = $Setting->save();
    
    // clear settings cache

    return $is_success;
}

Once I wrap my head around GIT and figure out the best place to put functions like this, I might be able to do this and send pull requests...

modxbot avatar Apr 27 '11 01:04 modxbot

everettg_99 submitted:

dammit... the function name should be updateOption

modxbot avatar Apr 27 '11 01:04 modxbot

bobray submitted:

This could also be done with another argument to setOption() that would trigger a permanent change to the DB.

BobRay avatar Apr 27 '11 03:04 BobRay

everettg_99 submitted:

Good call. The setOption() function is just begging for third option:

    /**
     * Sets an xPDO configuration option value.
     *
     * @param string $key The option key.
     * @param mixed $value A value to set for the given option key.
     */
    public function setOption($key, $value) {
        $this->config[$key]= $value;
    }

modxbot avatar Apr 27 '11 04:04 modxbot

Actually, it's not so easy as seems. Because settings also stored in contexts, user groups, and individual users and it's difficult to get a correct place for saving the current setting value. It does in both variants: with separated method and with third parameter for setOption()

alroniks avatar Jul 14 '17 22:07 alroniks

There could be one more argument to updateSetting(): settingType. It could be set to modSystemSetting, modContextSetting, modUserSetting, or modUserGroupSetting.

With that, it would look something like this:

   `
/**
* Convenience function to update or create system settings.
*
* @param   string  unique key identifying the setting to be updated or created (e.g., 'modUserSetting')
* @param   string  optional string value
*/
 public function updateSetting($key, $value='', $settingType = 'modSystemSetting') {

     $setting = $this->getObject($settingType, $key);
     if (! $setting)  {
         $setting = $this->newObject($settingType);
     }
     $success = false;
     if ($setting) {
         $setting->set('value', $value);
         $success = $setting->save();
     } else {
         $this->log(modX::LOG_LEVEL_ERROR, 'Unable to save or create ' . $settingType);
    }
    // clear settings cache

    return $success;
}

`

BobRay avatar Jul 15 '17 02:07 BobRay

Seem like a nice method. Want to prepare a PR for it @BobRay ?

OptimusCrime avatar Jul 15 '17 12:07 OptimusCrime

If I can find the time. ;)

What do you think about adding cacheFlag as a final argument, and if that's a good idea, should it default to true, false, or null?

Without the argument, it would default to null. The code (xPDOObject->save()) is not clear to me, so I'm not sure if having it set to null means the cache for the setting would be updated or not.

BobRay avatar Jul 16 '17 03:07 BobRay

This line:

$setting->set('value') = $value;

should be

$setting->set('value',$value);

jcamachott avatar Dec 20 '18 17:12 jcamachott

modContextSetting, modUserSetting, and modUserGroupSetting has field for relation to objects:

  • modContextSetting - context_key
  • modUserSetting - user
  • modUserGroupSetting - group

User can be a member of several groups. Which group should we select for default value?

ilyautkin avatar Jan 15 '19 08:01 ilyautkin

I think, each object have to update its own setting. Like this:

$modx->context->updateSetting($key, $value);
// ...
$modx->user->updateSetting($key, $value);
// ...
$user_group->updateSetting($key, $value);

ilyautkin avatar Jan 15 '19 08:01 ilyautkin

Does update really translate to "update the value of this object and persist it"? Introducing another way to modify and save values will only introduce more complexity into the codebase.

JoshuaLuckers avatar Jan 15 '19 11:01 JoshuaLuckers

Does update really translate to "update the value of this object and persist it"? Introducing another way to modify and save values will only introduce more complexity into the codebase.

I agree. I don't understand purpose of this issue. Is it actual?

ilyautkin avatar Jan 15 '19 11:01 ilyautkin

First, I think ilyautkin's idea (putting the methods in the MODX objects) is by far the best one (as long as the methods call the appropriate processor). It's not only intuitive, it's more convenient, and it makes the calls simpler and more uniform. It also helps bulletproof the process, since it cuts out the possibility of updating the wrong kind of setting. It's much better than my suggestion above.

The main point of convenience methods (besides convenience) is to avoid complexity, imo. They prevent new users from making mistakes (e.g., creating a new user in code without creating a user profile). It's very easy to create a MODX object in code that doesn't appear in the manager, won't work, and/or doesn't have the appropriate intersects objects set. These can crap up the database and cause very frustrating errors.

Users can call the appropriate update processor to make sure things get done right (and my code above should definitely have done that), but the processor paths are not easy to guess and the documentation is difficult to find:

$modx->runProcesssor('security/group/setting/update', $fields);
$modx->runProcesssor('security/user/setting/update', $fields);
$modx->runProcesssor('system/settings/update', $fields);
$modx->runProcessor('context/setting/update', $fields);

BobRay avatar Jan 16 '19 17:01 BobRay