CiviCRM Community Forums (archive)

*

News:

Have a question about CiviCRM?
Get it answered quickly at the new
CiviCRM Stack Exchange Q+A site

This forum was archived on 25 November 2017. Learn more.
How to get involved.
What to do if you think you've found a bug.



  • CiviCRM Community Forums (archive) »
  • Old sections (read-only, deprecated) »
  • Developer Discussion »
  • APIs and Hooks (Moderator: Donald Lobo) »
  • Settings API
Pages: 1 [2] 3 4

Author Topic: Settings API  (Read 5877 times)

Donald Lobo

  • Administrator
  • I’m (like) Lobo ;)
  • *****
  • Posts: 15963
  • Karma: 470
    • CiviCRM site
  • CiviCRM version: 4.2+
  • CMS version: Drupal 7, Joomla 2.5+
  • MySQL version: 5.5.x
  • PHP version: 5.4.x
Re: Settings API
October 10, 2012, 07:27:28 pm

not sure i understand this? Why dont you insert a default value in the setting table when adding that variable (in the upgrade script?)

lobo
A new CiviCRM Q&A resource needs YOUR help to get started. Visit our StackExchange proposed site, sign up and vote on 5 questions

Eileen

  • Forum Godess / God
  • I’m (like) Lobo ;)
  • *****
  • Posts: 4195
  • Karma: 218
    • Fuzion
Re: Settings API
October 10, 2012, 07:39:22 pm
I guess that's a more manual way of doing it - but achieves much the same thing.

But, at the moment I'm more concerned about svn users.
Make today the day you step up to support CiviCRM and all the amazing organisations that are using it to improve our world - http://civicrm.org/contribute

Eileen

  • Forum Godess / God
  • I’m (like) Lobo ;)
  • *****
  • Posts: 4195
  • Karma: 218
    • Fuzion
Re: Settings API
October 10, 2012, 07:46:25 pm
NB - on upgrade to 4.3 we need to run

2) run civicrm_api('setting','fill', array('version' => 3, 'domain_id' => 'all') ;

because non current domains have been neglected on upgrade for a while & are missing lots of settings that they should have

Make today the day you step up to support CiviCRM and all the amazing organisations that are using it to improve our world - http://civicrm.org/contribute

Eileen

  • Forum Godess / God
  • I’m (like) Lobo ;)
  • *****
  • Posts: 4195
  • Karma: 218
    • Fuzion
Re: Settings API
October 11, 2012, 12:11:44 am
OK - so looking at coverting the ones people are more interested in - the localisation settings. I see the $config object is called directly from tpl files. e.g

Any thoughts on the best approach to swap for a setting? Do I add a CRM API call?
 

<script type="text/javascript">
{literal}

var totalfee       = 0;
var thousandMarker = '{/literal}{$config->monetaryThousandSeparator}{literal}';
var seperator      = '{/literal}{$config->monetaryDecimalPoint}{literal}';
var symbol         = '{/literal}{$currencySymbol}{literal}';
var optionSep      = '|';
var priceSet = price = Array( );
cj("input,#priceset select,#priceset").each(function () {
Make today the day you step up to support CiviCRM and all the amazing organisations that are using it to improve our world - http://civicrm.org/contribute

xavier

  • Forum Godess / God
  • I’m (like) Lobo ;)
  • *****
  • Posts: 4453
  • Karma: 161
    • Tech To The People
  • CiviCRM version: yes probably
  • CMS version: drupal
Re: Settings API
October 11, 2012, 12:37:31 am
I would get directly the json out the api (btw dgg, that was the syntax I was mentioning at civicon

Code: [Select]
<script>
//CRM is a new global object introduced by Colemans for 4.3, I use it as a namespace to store civi variables

CRM.config = {crmAPI entity="setting"}; // implicit action get
console.log (CRM.config.monetaryDecimalPoint);

//or if you want only one value, this should work too
var seperator      = {crmAPI entity="setting" action="getvalue" return="monetaryDecimalPoint"};

</script>
Should work like that. if it doesn't, crmAPI is wrong and I'll fix it
« Last Edit: October 11, 2012, 12:46:39 am by xavier »
-Hackathon and data journalism about the European parliament 24-26 jan. Watch out the result

Eileen

  • Forum Godess / God
  • I’m (like) Lobo ;)
  • *****
  • Posts: 4195
  • Karma: 218
    • Fuzion
Re: Settings API
October 11, 2012, 01:12:32 am
Cool - I'll try that

Another one.

The custom separator is a pain with the xml so 3 options (or a combo of them)

1) Store settings metadata as a php array (as X suggested).
2) Store custom separated settings as a serialised array rather than a serialised custom separated string
3) Store custom separated settings as a serialised json string rather than a serialised custom separated string
4) Store custom separated settings as a non-serialised json string (but of course the other values would be serialised still (!)

Personally I'm leaning mostly towards #2 with #1 being possibly worth doing but not necessarily in response to this.
Make today the day you step up to support CiviCRM and all the amazing organisations that are using it to improve our world - http://civicrm.org/contribute

Eileen

  • Forum Godess / God
  • I’m (like) Lobo ;)
  • *****
  • Posts: 4195
  • Karma: 218
    • Fuzion
Re: Settings API
October 11, 2012, 02:54:22 am
On the crmAPI syntax .. this works!

Code: [Select]
   function calculatedPaymentAmount( ) {
       var thousandMarker = {/literal}{crmAPI entity="setting" action="getvalue" group="CiviCRM Localization" return="monetary_thousand_separator"}{literal};


Note that for getvalue the function requires group (because the underlying BAO function does).  The underlying BAO function for getvalue is different (faster) than the get function.
Make today the day you step up to support CiviCRM and all the amazing organisations that are using it to improve our world - http://civicrm.org/contribute

xavier

  • Forum Godess / God
  • I’m (like) Lobo ;)
  • *****
  • Posts: 4453
  • Karma: 161
    • Tech To The People
  • CiviCRM version: yes probably
  • CMS version: drupal
Re: Settings API
October 11, 2012, 04:49:58 am
Quote from: Eileen on October 11, 2012, 01:12:32 am
The custom separator is a pain with the xml so 3 options (or a combo of them)
1) Store settings metadata as a php array (as X suggested).
2) Store custom separated settings as a serialised array rather than a serialised custom separated string
3) Store custom separated settings as a serialised json string rather than a serialised custom separated string
4) Store custom separated settings as a non-serialised json string (but of course the other values would be serialised still (!)

Personally I'm leaning mostly towards #2 with #1 being possibly worth doing but not necessarily in response to this.

IMO, depends where it's stored.
If it's in a file (or can be), php array is probably the fastest, works fine with apc and easiest to read an if needed modify directly (I know you are not supposed to, but when developing has been proven handy)

If it's in db, json (because serialized array is not fun to hack mostly), but no big preference over php serialise.

What was the reason to store the cache in db for "static" stuff like the settings vs. generating a php file in a temp place ( template_c)?
Is there a big issue I'm missing with the idea of storing cached stuff like the config in a file config.{domain id}.php that contains a php array (or static var within a function)?
(and obviously generate it if not existing)

For get/getvalue, replacing the separator with an array will be way nicer and translates nicely to php array or json or xml at the end

For set/setvalue at least on the rest/ajax versions, it will likely be super useful to have a string with separator (like now eg. &return=sort_name,email,phone...)

Might be useful as well on php, because it's probably nicer to do fieldname=> "value" instead of fieldname => array("value") when dealing with an action where you set a multi value field with a single value (a common case, eg when having a single currency or single language configuration)
-Hackathon and data journalism about the European parliament 24-26 jan. Watch out the result

Donald Lobo

  • Administrator
  • I’m (like) Lobo ;)
  • *****
  • Posts: 15963
  • Karma: 470
    • CiviCRM site
  • CiviCRM version: 4.2+
  • CMS version: Drupal 7, Joomla 2.5+
  • MySQL version: 5.5.x
  • PHP version: 5.4.x
Re: Settings API
October 11, 2012, 07:31:19 am

for things like the directory / url path values, we store them in the settings table, BUT cache them in the config object

that way we avoided changing a lot of templates

Not sure if we should make function calls to "retrieve" the various setting values. So i suspect caching in the config object is still a good way :)

we have to make it easy for folks to change via UI. We should not assume people will hack a PHP file to modify settings

lobo
A new CiviCRM Q&A resource needs YOUR help to get started. Visit our StackExchange proposed site, sign up and vote on 5 questions

totten

  • Administrator
  • Ask me questions
  • *****
  • Posts: 695
  • Karma: 64
Re: Settings API
October 11, 2012, 11:02:00 am
I like the idea of caching the settings and avoiding civicrm_api() for a simple "read" operation -- that call-path and the syntax seem overwrought for accessing a simple setting.

There are a couple problems with using $config:

a) Downstream developers (extension authors) don't have the ability to add new fields to $config. So if core uses $config and downstream uses {crmAPI}, then it would get confusing.

b) The {civicrm_setting} table and its helper functions (getItem, setItem) use a performance optimization -- specifically, they organizes the settings into "groups" and load/cache settings on a per-group basis. I don't see how we could continue supporting this performance optimization if the recommended notation was "$config->my_setting". (OTOH, I don't know if we even need the optimization.)

I think we should consider
 * removing the notion of 'setting cache groups'
 * caching the entire list of settings (eg in civicrm_cache or memcache)
 * providing a sugary facade (eg PHP: "$config->settings->my_setting"; Smarty: "{$settings.my_setting}"

Eileen

  • Forum Godess / God
  • I’m (like) Lobo ;)
  • *****
  • Posts: 4195
  • Karma: 218
    • Fuzion
Re: Settings API
October 11, 2012, 01:25:27 pm
Ok so there seem to be a few things talked about here & not quite separated.

1) Settings Metadata - I am using this term to describe the Metadata ABOUT the possible settings. This includes the 'default' value & various other bits & pieces. It is hook editable & modules can set their own defaults. This should only be accessed during configuration actions (not getvalue actions as Tim pointed out these might occur during a batch job & needed to be 'snappy'). Revert & Fill actions are based on these (hook modified) results. Probably installing a 'localisation modules' would change the defaults & possibly 'revert' to them when it is enabled.

Currently Settings Metadata is stored in xml & is converted to an array when it is loaded - but X has made the case for changing that to a more drupal style set up where each Config file has a sensibly named function that returns an array. The custom separator breaks the xml. Apart from the effort involved in converting from xml to a php function I can't see a downside to doing that. Can anyone else?

2) The DB civicrm_settings table stores the actual settings in use for the site. Front end forms are unchanged but save to settings rather than to $config when I convert settings over (I did 2)

3) Changing the calls to retrieve the settings is a little yuck

      $thousands_sep = CRM_Core_BAO_Setting::getItem(
        CRM_Core_BAO_Setting::LOCALIZATION_PREFERENCES_NAME,
        'monetary_thousand_separator'
      );

A lot of the reason it is 'yuck' is not the model but the choice of groupnames - ie. we have the choice between

 
    [ul]CRM_Core_BAO_Setting::LOCALIZATION_PREFERENCES_NAME[/ul]
    [ul]CiviCRM Preferences[/ul]
    [/list]

    If the group name were simply 'core' then the key for the setting could become 'core_monetary_thousand_separator' (other examples would be mail_verp_separator & 'multisite_is_enabled' (rule would have to be one-word, lcase).

    4) Alternatively we could ditch the whole group field in exchange for removing the notion of 'setting cache groups' - probably this would be my first choice - but it would involve more change/ work.

    5) Makes sense to have REALLY high usage settings cached in the $config object - URLs & directories are the only ones that I would keep there (which is pretty much what has been done with other settings conversions).

    6) For the rest the following makes sense to me in tpl files
    {crmAPI entity="setting" action="getvalue"  return="core_monetary_thousand_separator"}
    or in php

    civicrm_api('settings', 'getvalue' array('return' => 'core_monetary_thousand_separator', 'version' => 3));

    drush civicrm-api setting.getvalue return=core_monetary_thousand_separator

    (And/Or Tim's $config object wrapper)

    7) most of the settings are pretty 'lean' but I wouldn't want to be loading up the big ones - e.g. country list , state_list as part of a generic cached settings array.
    Make today the day you step up to support CiviCRM and all the amazing organisations that are using it to improve our world - http://civicrm.org/contribute

    xavier

    • Forum Godess / God
    • I’m (like) Lobo ;)
    • *****
    • Posts: 4453
    • Karma: 161
      • Tech To The People
    • CiviCRM version: yes probably
    • CMS version: drupal
    Re: Settings API
    October 11, 2012, 02:04:15 pm

    Indeed, plenty of separate issues ends up mixed.

    On the cache thing, my question was NOT about changing anything about how CRM_Core_Config::singleton is used, but about how it's implemented.

    Namely, wouldn't it be better to simply generate a config.cache.php that contains the $config (or in as a static in a "namespace" function) instead of a serialized in a db row in civicrm_cache (or memcache)?

    So instead of reading civicrm_cache and unserialize it for each page, replacing that from a require_once. It's seems a trivial improvement. And trivial improvments tend to have a good reason they are not implemented. What I am missing?

    As for the groups, are the name of the settings unique across all the groups? We could keep the groups in the db and "flatten" them in the config/api.setting (probably going to cost a few more requests if the config isn't saved in the cache file, but shouldn't happen too often)

    P.S if needed for big config items (eg countries list) might be a worthwhile improvement to add a magic __get() so the $config->country is only loaded when needed.


    -Hackathon and data journalism about the European parliament 24-26 jan. Watch out the result

    totten

    • Administrator
    • Ask me questions
    • *****
    • Posts: 695
    • Karma: 64
    Re: Settings API
    October 11, 2012, 02:40:28 pm
    Quote from: xavier on October 11, 2012, 02:04:15 pm
    Namely, wouldn't it be better to simply generate a config.cache.php that contains the $config (or in as a static in a "namespace" function) instead of a serialized in a db row in civicrm_cache (or memcache)?

    I agree that the "config.cache.php" is probably a more performant caching mechanism than a serialized DB row.

    Quote from: xavier on October 11, 2012, 02:04:15 pm
    As for the groups, are the name of the settings unique across all the groups? We could keep the groups in the db and "flatten" them in the config/api.setting (probably going to cost a few more requests if the config isn't saved in the cache file, but shouldn't happen too often)

    Empirically, the names for domain settings are unique within the domain. We would want to set a stricter policy for naming them to prevent accidental collisions in the future (eg "tag_unconfirmed" should be called "campaign_tag_unconfirmed", but it's not worth the effort to rename it right now).

    Quote from: eileen
    7) most of the settings are pretty 'lean' but I wouldn't want to be loading up the big ones - e.g. country list , state_list as part of a generic cached settings array.

    Quote from: xavier on October 11, 2012, 02:04:15 pm
    P.S if needed for big config items (eg countries list) might be a worthwhile improvement to add a magic __get() so the $config->country is only loaded when needed.

    How about eliminating the property 'group_name (string)' and adding a simpler property 'prefetch (boolean)'. If prefetch is true, then the setting will be stored in the cached blob (config.cache.php or memcache or serialized DB row or whatever).

    Eileen

    • Forum Godess / God
    • I’m (like) Lobo ;)
    • *****
    • Posts: 4195
    • Karma: 218
      • Fuzion
    Re: Settings API
    October 11, 2012, 05:11:15 pm
    OK - so after some discussion with Lobo / Tim on IRC it seems the only option is to backtrack & go with

    civicrm_api('setting','create', array(
      'Directory Preferences:extensionDir' => x,
      'Multisite Preferences:is_enabled' => 1
    );

    Make today the day you step up to support CiviCRM and all the amazing organisations that are using it to improve our world - http://civicrm.org/contribute

    Eileen

    • Forum Godess / God
    • I’m (like) Lobo ;)
    • *****
    • Posts: 4195
    • Karma: 218
      • Fuzion
    Re: Settings API
    October 11, 2012, 06:41:36 pm
    This is how the UI version of the settings revert is currently looking
    Make today the day you step up to support CiviCRM and all the amazing organisations that are using it to improve our world - http://civicrm.org/contribute

    Pages: 1 [2] 3 4
    • CiviCRM Community Forums (archive) »
    • Old sections (read-only, deprecated) »
    • Developer Discussion »
    • APIs and Hooks (Moderator: Donald Lobo) »
    • Settings API

    This forum was archived on 2017-11-26.