validation on unbound form field - symfony-2.1

I have a form with an extra unbound field added using 'property_path' => false.
I would like to have a simple validation on this field and I've found many answers that suggest to use something like
$builder->addValidator(...);
but I've seen that in symfony 2.1 $builder->addValidator is deprecated. Does anyone know what is the correct way to put a validation on an unbound field in Symfony 2.1?

Edit :
I've just made a more complete answer on topic Symfony validate form with mapped false form fields
Original answer
Validating unbound (non mapped) field in a form is not well documented and the fast evolving form and validator components make the few examples obsoletes (for Symfony 2.1.2).
For now I succeed in validated non mapped fields with event listener.
Here is my simplified code :
namespace Dj\TestBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Form\FormEvents;
use Dj\TestBundle\Form\EventListener\NewPostListener;
class PostType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('lineNumber', 'choice', array(
'label' => 'How many lines :',
'choices' => array(
3 => '3 lines',
6 => '6 lines'
),
// 'data' => 3, // default value
'expanded' => true,
'mapped' => false
))
->add('body', 'textarea', array(
'label' => 'Your text',
'max_length' => 120));
// this listener will validate form datas
$listener = new NewPostListener;
$builder->addEventListener(FormEvents::POST_BIND, array($listener, 'postBind'));
}
// ... other methods
}
And the event listener :
namespace Dj\TestBundle\Form\EventListener;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormError;
/**
* listener used at Post creation time to validate non mapped fields
*/
class NewPostListener
{
/**
* Validates lineNumber and body length
* #param \Symfony\Component\Form\FormEvent $event
*/
public function postBind(FormEvent $event)
{
$form = $event->getForm();
$data = $event->getData();
if (!isset($data->lineNumber)) {
$msg = 'Please give a correct line number';
$form->get('lineNumber')->addError(new FormError($msg));
}
// ... other validations
}
}
This is how I validate my non mapped fields until I find out how to do this with validators.

I have the same problem from the docs we get this:
The interface FormValidatorInterface was deprecated and will be
removed in Symfony 2.3. If you implemented custom validators using
this interface, you can substitute them by event listeners listening
to the FormEvents::POST_BIND (or any other of the *BIND events). In
case you used the CallbackValidator class, you should now pass the
callback directly to addEventListener.
This suggest to use event listeners but I have not found and example.
https://github.com/symfony/symfony/blob/master/UPGRADE-2.1.md

Related

How to validate checkbox values using express-validator?

In my web front end form, I am using checkbox to select list of companies for each checkbox entry, I have given company name as 'value' attribute. In nodejs, I use express-validator to check the form. I am not clear how to validate and sanitize user input for these checkbox items.
I see all the example of express validator uses form parameter name to check a specific parameter (eg) check('userName') as middleware. But for checkboxes particular parameter will be present only when the user select that parameter. If I have 10 options and user select only 4 of them, then req.body will have only these parameters . And also I want all them pass through same validation check and sanitization. Please suggest how to do it.
I am using NodeJS version: 10.8
Express Validator: 5.3.0
My checkbox values are company_a1,company_a2,...company_a10. I tried to write custom Validator and check for each of the body parameter for alphanumeric value, but check is not raising error even if the value contain alphanumeric strings
async function validateReportParams(body, { req, loc, rpath }) {
for (const par of Object.keys(req.body)) {
try {
check(req.body[par].isAlphanumberic());
} catch (err) {
return Promise.reject(err);
}
}
}
exports.genReport = [
validateReq,
param().custom(validateReportParams),
async (req, res, next) => { ... }
];
Try using the same name for each checkbox than apply isIn([]) to validate as per: https://express-validator.github.io/docs/check-api.html
check(req.body.checkbox.isIn(['company_a1','company_a2',...,'company_a10']));
My answer is a little unrelated to this question.
but if you want to use an optional checkbox in your form.
you can do something like this
body('checkbox')
.customSanitizer(input => {
return Boolean(input)
})

Kohana 3.3 ORM Validation - unique value not working when value is empty

In a Model_Page class, extending the Kohana ORM class, I have this rules definition :
public function rules() {
return array(
'url' => array(
array('Model_Page::unique_url', array($this)),
),
);
}
To simplify here, I will just return false from this function, so it should never validate when I try to save/update a page :
public static function unique_url($page) {
return false;
}
This works as expected, if the value for url is not NULL or not an empty string.
But if I already have a page with an empty url, and that I try to add a new page with an empty url, the unique_url function is ignored, even when forcing a return false.
This could be a bug, but maybe I missed something...? In the Kohana docs, for the unique example, they use a username as an example, but the username also has a not_empty rule, which does not apply here.
Any help/suggestion appreciated!
I believe the rule is applied once you set the value, not when you're saving it.
I had a similar issue - the filter wasn't working if I didn't assign any value to the field. I've written my own save method:
public function save(Validation $validation = NULL)
{
if (!$this->loaded())
{
$this->ordering = 0;
}
return parent::save($validation);
}
this way the ordering would always be assigned for newly created objects and my filter would work.
And that's how I built another model. It's a company model that has a unique company name. Rules for the field are defined like this:
'name' => array(
array('not_empty'),
array('max_length', array(':value', 255)),
array(array($this, 'unique_name'))
)
And I have a method:
public function unique_name($value)
{
$exists = (bool) DB::select(array(DB::expr('COUNT(*)'), 'total_count'))
->from($this->_table_name)
->where('name', '=', $value)
->where($this->_primary_key, '!=', $this->pk())
->execute($this->_db)
->get('total_count');
return !$exists;
}
It basically checks if there are any other companies with the same name as the current one. Maybe this will give you the idea of what could be wrong with your solution.

ZF2: Switching Layouts Based on Idenitity - which event to use

To date I have had a single layout in my application, configured in module.config.php as follows:
'view_manager' => array(
'template_map' => array(
'layout/layout' => __DIR__ . '/../view/layout/layout.phtml',
),
I am now trying to switch the layout based on whether a user is logged in or not. This information is available in my Core\Auth service, and I am using it in my module.php as follows:
public function onBootstrap(MvcEvent $e)
{
...
$eventManager->attach('dispatch', function ($e) {
$application = $e->getApplication();
$auth = $application->getServiceManager()->get('Core\Auth');
if (!$auth->isLoggedIn()) {
$viewModel = $e->getViewModel();
$viewModel->setTemplate('layout/public');
}
}, -1000000);
}
The problem is that I don't know which event to attach it to, and which priority to use. If I attach it to:...
...the bootstrap or route event, it gets overridden
...the dispatch event with a high priority it gets overridden
...the dispatch event with a low priority, it overrides any layout changes that controller actions might make, e.g. $view->setTerminal(true)
...the render event, (again) it overrides changes made by actions
Where should I be attaching it? And with what priority?
Opps, my mistake.
I was doing the same isLoggedIn() test in my index/index action, which was muddying the results. I have removed it and attached the layout switch to the route event, default priority, and so far it works fine!

How to validate a POST of a non standard action in Cake PHP 1.3

Using CakePHP 1.3
I have a controller with a non standard action name - say:
class WidgetsController extends AppController {
function modifyColor($id = null) {
// Some code that modifies the background color of a widget
}
}
and a companion view views/widgets/modifyColor.ctp
The modifyColor template POSTS to the action:
echo $this->Form->create('User',array('url' => array('controller' => 'widgets', 'action' => 'modifyColor')));
I get a 404 on the POST since the CakePHP Security component is trying to validate the form
and I would like to be able to validate the POST.
The only way I can get this to work seems to be to turn off POST validation
if ($this->action == 'modifyColor') {
$this->Security->validatePost = false;
}
This seems a bad solution.
How do I use the Security component on a non standard action?
allowedActions doesn't seem to work
Thanks
Danny
Answering my own question.
A. There is no problem with using any-named actions in CakePHP
B. A conceptual bug with CakePHP related to using the same function for the Form GET and Form POST
On the Form GET I had this:
if (empty($this->data)) {
$this->data = $this->Widget->read(null, $id);
}
The Form itself had some code like this:
echo $this->Form->input('id');
echo $this->formView('Current color', 'CurrentColor');
echo $this->formView('New color', 'NewColor');
echo $this->formView('New background color', 'BackgrdColor');
Which was fine, except that none of these fields appear in the Widget model - and the CakePHP Security component interprets this as a sort of XSRF attack - since it is finding fields in the form that don't belong to the model. That's why:
$this->Security->validatePost = false;
solved the "problem".
The correct solution is simply not to populate $this->data with the model in the controller action and handle the field assignments on the POST:
function modcolor () {
$this->layout = 'app_ui_listview';
if (!empty($this->data)) {
$id = $this->Session->read('Auth.User.id');
$u = $this->Widget->read(null, $id);
// Assign fields from the form to the model....
}
}
the problem is you are trying to pass url and you are trying to pass the controller stuff too.
echo $this->Form->create('Widget', array('controller' => 'widgets', 'action' => 'modifyColor'));
or
echo $this->Form->create('Widget', array('url' => '/widgets/modifyColor'));

Hook into Drupal registration and validate user info against business logic

I want to hook into the registration module. I already have a database of 50000 users who use my old website. Now I am migrating to Drupal.
I still haven't migrated the entries to drupal database. I will be checking against my old database.
When a user tries to register in Drupal, I need to check whether the username he gave is already present in that list of 50000 (and growing) entries. If it exists, I need to cancel the registration showing an error msg saying username exists..
Which hook should I use? If my code figures that the validation failed, How can I tell drupal to display an error msg?
Edit: I hooked into the hook_user and checked for the 'validate' op. I am able to validate and assign error messages. But it is happening for all forms. I want to validate only the new account creation form. How can I do that?
Thanks.
You should register an additional validation callback function for the registration form using hook_form_FORM_ID_alter(), somewhat like so:
// Alter the registration form
function yourModuleName_form_user_register_alter(&$form, &$form_state) {
// Add your own function to the array of validation callbacks
$form['#validate'][] = 'yourModuleName_user_register_validate';
}
// Perform your own validation
function yourModuleName_user_register_validate($form, &$form_state) {
// Extract the submitted name
$name = $form_state['values']['name'];
// Check it according to your own logic
$is_valid_name = your_check_for_valid_name();
// File error, when not valid
if (!$is_valid) {
form_set_error('name', t('Name already taken, please choose a different one'));
}
}
Henrik Opel answer work on Drupal 6. For Drupal 7 use yourModuleName_form_user_register_form_alter
Here are some examples for Drupal 7:
/**
* Implements of hook_user_insert().
*/
function foo_user_insert(&$edit, $account, $category) {
// foo_user_submit($edit, $account);
}
/**
* Implementation of hook_user_delete().
*/
function foo_user_delete($account) {
// foo_user_delete($account);
}
/**
* Implements hook_form_FORM_ID_alter().
* Form ID: user_register_form
*/
function foo_form_user_register_form_alter($form, &$form_state) {
if ($form['#user_category'] == 'account' && !isset($form['#user']->uid)) {
// Foo code
}
}
/**
* Implements hook_form_FORM_ID_alter().
* Form ID: user_profile_form
*/
function foo_form_user_profile_form_alter($form, &$form_state) {
// Set a custom form validate and submit handlers.
$form['#validate'][] = 'foo_account_validate';
$form['#submit'][] = 'foo_account_submit';
}
/**
* Implements of hook_form_alter().
* This is the same as: hook_form_FORM_ID_alter()
*/
function foo_form_alter(&$form, $form_state, $form_id) {
switch ($form_id) {
case "user_profile_form":
case "user_register_form":
break;
}
}
Consider using the Username Originality AJAX check module: https://www.drupal.org/project/username_check

Resources