php - Symfony custom validation not working -
i've created custom form validator not seem working. gets called during form submission , returns false when should fail validation. doesn't seem tell form validation has failed.
here form validator: (code box scrolls)
<?php namespace redacted\appbundle\validator\constraints; use symfony\component\httpfoundation\requeststack; use symfony\component\validator\constraint; use symfony\component\validator\constraintvalidator; class requiredifplainpasswordsetvalidator extends constraintvalidator { /** * requeststack instance. * * @var symfony\component\httpfoundation\requeststack */ protected $requeststack; /** * dependency injection. * * @param symfony\component\httpfoundation\requeststack $requeststack */ public function __construct(requeststack $requeststack) { $this->requeststack = $requeststack; } /** * if plain password has been set, current password must not * empty. * * @param string $currentpassword * @param symfony\component\validator\constraint $constraint * * @return bool */ public function validate($currentpassword, constraint $constraint) { $plainpassword = $this->requeststack->getcurrentrequest()->request ->get('security_settings')['plainpassword']['first']; if ($plainpassword && !$currentpassword) { return false; } return true; } }
and here constraint goes it:
<?php namespace redacted\appbundle\validator\constraints; use symfony\component\validator\constraint; /** * @annotation */ class requiredifplainpasswordset extends constraint { /** * error message * * @var string */ protected $message = 'please enter current password.'; /** * alias related validator in services.yml * * @return string */ public function validatedby() { return 'required_if_plain_password_set'; } }
and relevant part of app/config/services.yml
:
services: redacted.appbundle.required_if_plain_password_set: class: redacted\appbundle\validator\constraints\requiredifplainpasswordsetvalidator arguments: ["@request_stack"] tags: - { name: validator.constraint_validator, alias: required_if_plain_password_set }
i've created custom form type: (code box scrolls)
<?php namespace redacted\appbundle\form; use symfony\component\optionsresolver\optionsresolver; use symfony\component\form\formbuilderinterface; use symfony\component\form\abstracttype; class securitysettingsformtype extends abstracttype { /** * name of form type * * @return string */ public function getname() { return 'security_settings'; } /** * add fields form * * @param symfony\component\form\formbuilderinterface $formbuilder * @param array $options */ public function buildform(formbuilderinterface $formbuilder, array $options) { $formbuilder ->add('email') ->add('currentpassword', 'password') ->add('plainpassword', 'repeated', [ 'type' => 'password', 'invalid_message' => 'passwords must match.', ]); } /** * configureoptions. * * @param symfony\component\optionsresolver\optionsresolver $resolver */ public function configureoptions(optionsresolver $resolver) { $options = [ 'data_class' => 'appbundle\entity\user', 'validation_groups' => ['security_settings'], ]; $resolver->setdefaults($options); } }
which validates against user
entity due data_type
. here relevant part of user
entity:
<?php namespace redacted\appbundle\entity; use doctrine\orm\mapping orm; use symfony\component\security\core\user\userinterface; use symfony\component\validator\constraints assert; use redacted\appbundle\validator\constraints\requiredifplainpasswordset; class user implements userinterface, \serializable { // ... /** * @var string (default: null) * * @assert\notblank(message="user.email_required", groups={"security_settings"}) * @assert\email(message="security_settings.valid_email" groups={"security_settings"}) * @orm\column(name="email", type="string", length=255, nullable=true, unique=true) */ private $email = null; /** * current password - used validation * * @requiredifplainpasswordset( * message="security_settings.current_password_required", * groups={"security_settings"} * ) * @var string */ protected $currentpassword; // ... setters , getters above, etc. }
and finally, here's controller method i'm using check. i'll leave out view because it's irrelevant. (i'm defining controller service no redirecttoroute()
, etc.)
// in controller class... /** * security settings page - email, password, etc. * * @route("/security-settings", name="security_settings") * @template() * * @param symfony\component\httpfoundation\request $request * * @return array|symfony\component\httpfoundation\redirectresponse */ public function securitysettingsaction(request $request) { $loggedinuser = $this->tokenstorage->gettoken()->getuser(); $form = $this->formfactory ->create(new securitysettingsformtype(), $loggedinuser); $form->handlerequest($request); if ($form->isvalid()) { $user = $form->getdata(); // persist user $this->saveusersettings($user); // set success message $this->setsecuritysettingsflashsuccess($request); // redirect $route = $this->router->generate('security_settings'); return new redirectresponse($route); } return ['form' => $form->createview()]; }
the idea current password should required if new password entered. although validate()
function getting called , returning false when should, form's isvalid()
returning true , it's saving. if add @assert\notblank(groups={"security_settings"})
assertion user::currentpassword
field, does fire , fail successfully, is looking validation annotations on field.
what missing?
the problem validate()
method of constraintvalidator
should not return true or false, should build violation so:
/** * if plain password has been set, current password must not * empty. * * @param string $currentpassword * @param symfony\component\validator\constraint $constraint */ public function validate($currentpassword, constraint $constraint) { $plainpassword = $this->requeststack->getcurrentrequest()->request ->get('security_settings')['plainpassword']['first']; if ($plainpassword && !$currentpassword) { $this->context->buildviolation($constraint->message) ->atpath('currentpassword')->addviolation(); } }
thanks coworker catching it. works expected now.
Comments
Post a Comment