How to extend validation rules for items in plugin

Hi,
I wonder how should I extend validation rules for Item model in my plugin. Example of such a custom validation rule is that I want to require certain fields = not empty.
The rules are inside Item::_validate() method, but there is no filter for adding new ones. beforeSave callback doesn’t care about return values either, so should I simply throw exception if my custom validation fails? Or what would you recommend?
Thanks,
Luk

Found it! For anybody looking for solution, I did this:

public function hookBeforeSaveItem($args)
{
    $args['record']->addError('my_field', __('My field must be specified'));
}

Because model validation is checking existence of errors.

Hello, @luk.puk

Could you show us an example of the validation you’re accomplishing?
Because I’m trying to do something similar, but using hookBeforeSaveItem I seem not to be able to get any value to check. Here’s my code:

public function hookBeforeSaveItem($args)
{
	$item = $args['record'];
	$title = $item->metadata('Dublin Core', 'Title');
	if(empty($title)) {
		$item->addError("DC Title", __('DC Title cannot be empty!'));
	}
}

When pressing the button, $title is empty, no matter what I’ve typing in the field.
Thanks in advance.

Edit: it works fine with an Item already existing (so, when editing), but not with a new Item that’s going to be added. That’s probably because the check is done on information already (or not yet) available in the db, instead of the actual content of the input fields in the form.

The point is that in beforeSaveItem hook the posted texts are not saved in database yet, so you cannot retrieve it with $item->getElementTexts('Dublin Core', 'Title'). Only when you’re editing existing item will you get DC:Title, but not the submitted one, which is what you want.
I used custom validation only for add and edit actions (validating POST data), so it doesn’t work when doing batch-edit or importing items from CSV, etc. Example:

public function hookBeforeSaveItem($args)
{
    $item = $args['record'];
    $post = $args['post'];
    // if POST is empty, skip the validation, so it doesn't break when saving item in another way
    if (!empty($post)) {
        // you may simply hardcode DC:Title element id, but it's safer for Item Type Metadata elements
        $titleElement = $item->getElement('Dublin Core', 'Title');
        $title = '';
        if (!empty($post['Elements'][$titleElement->id])) {
            foreach ($post['Elements'][$titleElement->id] as $text) {
                $title .= trim($text);
            }
        }
        if (empty($title)) {
            $item->addError("DC Title", __('DC Title cannot be empty!'));
        }
    }
}

Hope it helps.

Actually… the above function needed a little fixing, because of multiple arrays nested. Here’s the working version:

public function hookBeforeSaveItem($args)
{
    $item = $args['record'];
    $post = $args['post'];
    // if POST is empty, skip the validation, so it doesn't break when saving item in another way
    if (!empty($post)) {
        // you may simply hardcode DC:Title element id, but it's safer for Item Type Metadata elements
        $titleElement = $item->getElement('Dublin Core', 'Title');
        $title = '';
        if (!empty($post['Elements'][$titleElement->id])) {
            foreach ($post['Elements'][$titleElement->id] as $textbox) {
                $title .= trim($textbox['text']);
            }
        }
        if (empty($title)) {
            $item->addError("DC Title", __('DC Title cannot be empty!'));
        }
    }
}

Hope this helps.

1 Like