5

I have a plugin that has a few settings. One of which is a start date and and end date. Everything is set up and working fine. I'd like to validate the start/end dates a a bit though.

I am able to use compare to check that the end isn't before the start, but I'd also like to check that the start (or end) isn't in the past as well.

Using this awesome page on validation I've seen how to set custom validation via rules. But, since I'm in a settings file, I'm not exactly sure how this translates over.

MyPlugin.php

defineSettings(){
    return array(
        'myStartDate' => array(
             AttributeType::DateTime,
             'required': true,
             'compare': '<= myEndDate'
         ),
         'myEndDate' => array(
             AttributeType::DateTime,
             'required': true,
             'compare': '>= myStartDate'
         ),
    )
}

What I think I'm trying to get is something like this:

....
'myStartDate' => array(
     AttributeType::DateTime,
     'required': true,
     'something': array(
          'rule': myValidation,
          'message': 'The start date can not be after the finish date.'
      ) 
 )
....

function myValidation() {
    // Do something here
}

Or, maybe I'm way off.

3

It sounds like you're on the right track. You could create a custom validator, as detailed here.

<?php namespace Craft;

use Carbon\Carbon;

class MyPlugin_ExampleModel extends BaseModel
{
    protected function defineAttributes()
    {
        return [
            'startDate' => [
                'type'     => AttributeType::DateTime,
                'required' => true,
                'compare'  => '<= endDate',
            ],
            'endDate' => [
                'type'     => AttributeType::DateTime,
                'required' => true,
                'compare'  => '>= startDate',
            ],
        ];
    }

    public function rules()
    {
        $rules = parent::rules();

        $rules[] = ['startDate', 'validateFutureDate'];
        $rules[] = ['endDate', 'validateFutureDate'];

        return $rules;
    }

    public function validateFutureDate($attribute)
    {
        $value = $this->$attribute;

        if ($value && Carbon::now()->gte($value)) {
            $message = Craft::t("Date must be in the future");
            $this->addError($attribute, $message);
        }
    }
}

You can also extract the validation into a separate class, which would make it easier to test (details are in the aforementioned article).

Caveats and disclaimers

This code is completely untested. In particular, I'm not sure whether the date comparison will work with the attribute value as-is. You'll probably also want to check what happens to the custom validation if the value contains an invalid date-time string.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.