# How do I save a Plugin's date settings-field?

I've got a plugin with some custom settings, like this:

protected function defineSettings()
{
return array(
'serviceendpoint' => array(AttributeType::String, 'required'=>true),
'passkey' => array(AttributeType::String, 'required'=>true),
'newregistrationdate' => array(AttributeType::DateTime, 'required'=>false),
);
}


Then I have a _settings template, which renders the form:

{{ forms.textField({
first:        true,
label:        "CRM Endpoint URL"|t,
id:           'serviceendpoint',
name:         'serviceendpoint',
instructions: "The URL for the CRM service ."|t,
value:        settings.serviceendpoint,
autofocus:    true,
placeholder: "https://example.com/api/...",
errors:       settings.getErrors('serviceendpoint')
}) }}

{{ forms.textField({
label:        "The service passkey"|t,
id:           'passkey',
name:         'passkey',
instructions: ""|t,
value:        settings.passkey,
placeholder: "1234...",
errors:       settings.getErrors('passkey')
}) }}

<pre>Val: "{{ dump(settings.newregistrationdate) }}"</pre>
{{ forms.dateField({
label:        "New registrations after this date"|t,
id:           'newregistrationdate',
name:         'newregistrationdate',
instructions: "Users registered after this date will get a welcome email"|t,
value:        settings.newregistrationdate.date|default,
errors:       settings.getErrors('newregistrationdate')
}) }}


The String-typed values are saved just fine. But the DateTime always comes back as false.

I've tried adding a prepSettings function, and doing:

 $settings['newregistrationdate'] = new DateTime($settings['newregistrationdate']['date']);


but it makes no difference.

What does prepSettings have to return for DateTime typed fields?

Yup, you need to use AttributeType::Mixed as Justin Kimbrell suggests. The date will then be escaped and stored in the database like this: *

{"newregistrationdate":{"date":"2\/1\/2015"}}

Now, the dateField in your settings template will expect a DateTime object for its value – so just passing getSettings() as is will make it choke. You can get around that by adding the following to the getSettingsHtml() method:

$settings =$this->getSettings();
if ( isset( $settings[ 'newregistrationdate' ][ 'date' ] ) ) {$settings[ 'newregistrationdate' ] = new DateTime( $settings[ 'newregistrationdate' ][ 'date' ] ); } return craft()->templates->render( 'yourPluginHandle/settings', array( 'settings' =>$settings,
) );


...and then finally, make sure the dateField constructor looks in the right place for its value by removing the date key of the settings.newregistrationdate property:

{{ forms.dateField({
label:        "New registrations after this date"|t,
id:           'newregistrationdate',
name:         'newregistrationdate',
instructions: "Users registered after this date will get a welcome email"|t,
value:        settings.newregistrationdate,
errors:       settings.getErrors('newregistrationdate')
}) }}


Solution is tested.

• Note that the date object is actually serialized, escaped and stored properly even if you use AttributeType::DateTime, however getSettings() will always return the attribute value as false. Could be a bug?
• Mats thanks for your answer, for field types I use Craft's DateTime::createFromString helper function (following Brandon's how-to). Any idea why I don't get this to work for my plugin settings? I use the function in both, prepSettings and getSettingsHtml. The data gets saved in array format including timezone etc. and not in "2015-02-24 10:23:00" format as for all other datetime data I have. Any ideas? – carlcs Feb 24 '15 at 10:22
• carlcs, I don't really know, sorry. Like Justin Kimbrell points out, it looks like the settings model can't handle the serialized DateTime, so it returns false. The only thing I've been able to store and retrieve is a plain old serialized array (using AttributeType::Mixed). Would be interesting to hear the Craft guys chime in, whether this is a bug or if there's a way around it. As for the DateTime::createFromString helper, in the OP's case it doesn't really matter which is used, that or new DateTime() – although I guess the former is best practice. – Mats Mikkel Rummelhoff Feb 24 '15 at 10:31
• FWIW, this has been fixed in Craft 3 and probably won't be officially fixed in the 2.x branch. – Brad Bell Apr 7 '15 at 20:01
• @MatsMikkelRummelhoff No worries! – Brad Bell Apr 7 '15 at 20:33
• Thanks for this @mmikkel - so useful! I had one extra wrinkle - the dates entered in my forms are dd/mm/yyyy which DateTime() complains about. So I had to do new DateTime( str_replace('/', '-', \$settings['newregistrationdate']['date']) ). I imagine this is locale dependent. If your site's multilingual, then users can change their locale in 'My Account' which may complicate things further - each user submitting dates in different formats? – Phil Gyford Sep 3 '15 at 9:36

I didn't have time to setup this scenario locally, but you may want to use AttributeType::Mixed. I believe the dateField macro returns the value as an array, so using AttributeType::Mixed should allow that value to be saved. All your other code looks correct, so it has to be your settings model not getting populated correctly.