silverstripe-framework/src/Security/Member_Validator.php

147 lines
3.7 KiB
PHP

<?php
namespace SilverStripe\Security;
use SilverStripe\Forms\RequiredFields;
use SilverStripe\Forms\GridField\GridFieldDetailForm_ItemRequest;
/**
* Member Validator
*
* Custom validation for the Member object can be achieved either through an
* {@link DataExtension} on the Member_Validator object or, by specifying a subclass of
* {@link Member_Validator} through the {@link Injector} API.
* The Validator can also be modified by adding an Extension to Member and implement the
* <code>updateValidator</code> hook.
* {@see Member::getValidator()}
*
* Additional required fields can also be set via config API, eg.
* <code>
* Member_Validator:
* customRequired:
* - Surname
* </code>
*/
class Member_Validator extends RequiredFields
{
/**
* Fields that are required by this validator
* @config
* @var array
* @skipUpgrade
*/
protected $customRequired = array(
'FirstName',
'Email'
);
/**
* Determine what member this validator is meant for
* @var Member
*/
protected $forMember = null;
/**
* Constructor
*/
public function __construct()
{
$required = func_get_args();
if (isset($required[0]) && is_array($required[0])) {
$required = $required[0];
}
$required = array_merge($required, $this->customRequired);
// check for config API values and merge them in
$config = $this->config()->customRequired;
if (is_array($config)) {
$required = array_merge($required, $config);
}
parent::__construct(array_unique($required));
}
/**
* Get the member this validator applies to.
* @return Member
*/
public function getForMember()
{
return $this->forMember;
}
/**
* Set the Member this validator applies to.
* @param Member $value
* @return $this
*/
public function setForMember(Member $value)
{
$this->forMember = $value;
return $this;
}
/**
* Check if the submitted member data is valid (server-side)
*
* Check if a member with that email doesn't already exist, or if it does
* that it is this member.
*
* @param array $data Submitted data
* @return bool Returns TRUE if the submitted data is valid, otherwise
* FALSE.
*/
public function php($data)
{
$valid = parent::php($data);
$identifierField = (string)Member::config()->unique_identifier_field;
// Only validate identifier field if it's actually set. This could be the case if
// somebody removes `Email` from the list of required fields.
if (isset($data[$identifierField])) {
$id = isset($data['ID']) ? (int)$data['ID'] : 0;
if (!$id && ($ctrl = $this->form->getController())) {
// get the record when within GridField (Member editing page in CMS)
if ($ctrl instanceof GridFieldDetailForm_ItemRequest && $record = $ctrl->getRecord()) {
$id = $record->ID;
}
}
// If there's no ID passed via controller or form-data, use the assigned member (if available)
if (!$id && ($member = $this->getForMember())) {
$id = $member->exists() ? $member->ID : 0;
}
// set the found ID to the data array, so that extensions can also use it
$data['ID'] = $id;
$members = Member::get()->filter($identifierField, $data[$identifierField]);
if ($id) {
$members = $members->exclude('ID', $id);
}
if ($members->count() > 0) {
$this->validationError(
$identifierField,
_t(
'Member.VALIDATIONMEMBEREXISTS',
'A member already exists with the same {identifier}',
array('identifier' => Member::singleton()->fieldLabel($identifierField))
),
'required'
);
$valid = false;
}
}
// Execute the validators on the extensions
$results = $this->extend('updatePHP', $data, $this->form);
$results[] = $valid;
return min($results);
}
}