Zend form validation multiple custom validation message for same field at the same time - forms

I have a Zend form password custom validation.
I have set the addValidator functions IInd argument to false since I need to get all errors at once. Both of my validation classes have set the self::INVLID to corresponding error messages.
But when I look in the Zend controller even though both validations fail I'm getting only one (the last) error message.
I need all the error messages at once.
/* Form validation*/
$passwordSpecialValidator = new Passwordspecialvalidationvalidator();
$passwordHistoryValidator = new Passwordhistorylvalidationvalidator(new model(), $username, $newpass);
$this->newpass->addValidator($passwordSpecialValidator, false)
->addValidator($passwordHistoryValidator, false);
/* One validation class */
class Passwordhistorylvalidationvalidator extends Zend_Validate_Abstract {
const INVLID = '';
protected $_messageTemplates = array(
self::INVLID => 'Your password doesnt meet the history requirements'
);
public function __construct($model, $username, $password) {
$this->_model = $model;
$this->_username = $username;
$this->_password = $password;
}
public function isValid($value, $context = null) {
if ($this->_username == "") {
$auth = Zend_Auth::getInstance();
if ($auth->hasIdentity()) {
$arrayResult = $auth->getIdentity();
if (isset($arrayResult->username)) {
$this->_username = $arrayResult->username;
}
}
}
$passwordExists = false;
$oldPasswords = $this->_model->getHistoryPasswords($this->_username, $this->_password);
if (count($oldPasswords) > 0) {
$passwordExists = true;
}
if ($passwordExists == false) {
return true;
} else {
$this->_setValue($value);
$this->_error(self::INVLID);
return false;
}
}
}
/* Getting error messages */
foreach ($objForm->getMessages() as $messages) {
foreach ($messages as $message) {
$errMessages[] = $message;
}
}
But the array $errMessages has only the last validation message (without index) even though both special validation and history validation fails. How would I get both error messages in an array if both validations fail?

Related

Upload multiple images using a many-to-many using Yii2

How to make loading multiple images and making many-to-many relationships on a table of apartments?
I have a model Apartment:
public function getApartmentImages()
{
return $this->hasMany(ApartmentImages::className(), ['apartment_id' => 'id']);
}
public function getImages()
{
return $this->hasMany(Images::className(), ['id' => 'image_id'])
->via('apartmentImages');
}
Model Images:
public function getApartmentImages()
{
return $this->hasMany(ApartmentImages::className(), ['image_id' => 'id']);
}
/**
* #return \yii\db\ActiveQuery
*/
public function getApartments()
{
return $this->hasMany(Apartment::className(), ['id' => 'apartment_id'])
->via('apartmentImages');
}
Model ApartmentImages
public function getImage()
{
return $this->hasOne(Images::className(), ['id' => 'image_id']);
}
public function getApartment()
{
return $this->hasOne(Apartment::className(), ['id' => 'apartment_id']);
}
The apartment has a main image (layout) and many others.
I managed to make the layout load:
public function actionCreate()
{
$model = new Apartment();
$model->load(Yii::$app->getRequest()->getBodyParams(), '');
$layout = new Images();
$layout->imageFile = UploadedFile::getInstanceByName('layout');
if ($layout->upload()) {
$model->layout_id = $layout->id;
}
if ($model->validate()) {
if ($model->save()) {
$response = Yii::$app->getResponse();
$response->setStatusCode(201);
$id = implode(',', array_values($model->getPrimaryKey(true)));
$response->getHeaders()->set('Location', Url::toRoute(['view', 'id' => $id], true));
} elseif (!$model->hasErrors()) {
throw new ServerErrorHttpException('Failed to create the object for unknown reason.');
}
}
return $model;
}
I filled the array with all the sent pictures, and in the loop I upload to the site, and using
//INSERT INTO `apartment_images` (`apartment_id`, `image_id`) VALUES (...)
$model->link('images', $images[0]);
I create an entry in the link table.
public function actionCreate()
{
$model = new Apartment();
$model->load(Yii::$app->getRequest()->getBodyParams(), '');
$layout = new Images();
$layout->imageFile = UploadedFile::getInstanceByName('layout');
$layout->validate();
if ($layout->upload()) {
$model->layout_id = $layout->id;
}
$count = count(UploadedFile::getInstancesByName('images'));//Get the number of images
$images = [new Images()];//First image required
$images[0]->imageFile = UploadedFile::getInstanceByName('images[0]');
if(!$images[0]->validate()) return $images[0]->errors;//Check errors
if ($model->validate()){
if ($model->save()) {
if ($images[0]->upload()) {
$model->link('images',$images[0]);//Binding many to many
}
for($i = 1; $i < $count; $i++) {//Check the rest and repeat again
$images[$i] = new Images();
$images[$i]->imageFile = UploadedFile::getInstanceByName('images['.$i.']');
if ($images[$i]->upload()) {
$model->link('images',$images[$i]);
}
}
$response = Yii::$app->getResponse();
$response->setStatusCode(201);
$id = implode(',', array_values($model->getPrimaryKey(true)));
$response->getHeaders()->set('Location', Url::toRoute(['view', 'id' => $id], true));
} elseif (!$model->hasErrors()) {
throw new ServerErrorHttpException('Failed to create the object for unknown reason.');
}
}
else return $model->errors;
return $model;
}

codeigniter form validation always returns false even when rules met

Problem: even if my form fields meet the rules the codeigniter form validation still returns false (error).
example:
public function edit(){
$this->load->library('form_validation');
$this->form_validation->set_rules('title', 'title', 'required|xss_clean|trim|is_unique[news.Title]');
$this->form_validation->set_rules('description', 'description', 'required|xss_clean|trim');
$this->form_validation->set_rules('notes', 'notes', 'required|xss_clean|trim');
if ($this->form_validation->run() == FALSE)
{
$data['error'] = '';
$data['page_title']="Edit News";
echo "error";
}
else {
..........
if i leave the fields empty it will tell me to enter something because they cant be left empty. if i type something then it returns error once i submit the form.
you have to use the callback validation function
you have to pass id also
$this->form_validation->set_rules('title', 'Title', 'required|xss_clean|trim|callback_check_title');
function check_title($title) {
if($this->input->post('id'))
$id = $this->input->post('id');
else
$id = '';
$result = $this->news_model->check_unique_title($id, $title);
if($result == 0)
$response = true;
else {
$this->form_validation->set_message('check_title', 'Title must be unique');
$response = false;
}
return $response;
}
in model
function check_unique_title($id, $title) {
$this->db->where('title', $title);
if($id) {
$this->db->where_not_in('id', $id);
}
return $this->db->get('news')->num_rows();
}
it will work for both insert and update
no need for callback function
The problem is : codeigniter database class is not loaded;
You should load database : $this->load->database(); before running
if ($this->form_validation->run() == FALSE)
{
$data['error'] = '';
$data['page_title']="Edit News";
echo "error";
}

set user id based on pk when logged in through facebook

I am able to login/logout on my web app using facebook. But the problem is when the user needs to update his profile on my application, he can't. It would say that he is restricted to view his own page. The only way for this to happen is that user identity is probably not set. But I am not sure how to correct this. When I tried Yii::app()->user->user_id the Id is actually correct id, which is the pk in user model. So how is it that he cannot get to update his own page?
in my facebookUserIdentity:
public function authenticate()
{
if($this->getIsAccessTokenValid() && $this->setFBUser())
{
$this->_user = $this->getUserFromDatabase();
if($this->_user === false)
return false;
$this->setState('isUser', false);
$this->setState('isAdmin', false);
$this->setState('isShop', false);
$this->setState('isSuper', false);
$this->setState('user',$this->_user);
$this->_id = $this->_FBUser['id'];
//I've tried doing something like $this->_id = Yii::app()->user->user_id; or like $this->_user->user_id; ?
$this->_name = $this->_FBUser['name'];
return true;
}
else {
return false;
}
}
getting user from db:
protected function getUserFromDatabase()
{
$FBUser = $this->_FBUser;
if($FBUser)
{
$user = User::model()->findByAttributes (array('oauth_uid'=>$FBUser['id']));
if(!$user)
{
$user = new User;
$user->oauth_uid = $FBUser['id'];
$user->username = $FBUser['id'];
$user->first_name = $FBUser['first_name'];
//other info etc
$user->image = "https://graph.facebook.com/" . $FBUser['id'] . "/picture?type=large";
}
else
{
if ($user->oauth_permission == 'n')
{
$this->errorMessage = self::ERROR_LOGIN_DISABLE;
return false;
}
$user->last_login_date = date('Y-m-d H:i:s');
}
if($user->save())
{
return $user;
}
else
$this->errorMessage = CJSON::encode ( $user->getErrors());
return false;
}
else {
$this->errorMessage = "Failed getting facebook user data";
return false;
}
}
and lastly, the controller page rules:
public function accessRules()
{
$params=array();
$id=Yii::app()->request->getParam('id');
$params['model']=$this->loadModel($id);
return array(
//stuff
array('allow', // allow authenticated user to perform 'create' and 'update' actions
'actions'=>array('create','update','RemoveImage'),
'roles'=>array('admin','super','owner'=>$params),
),
//stuff

how to save a collection form in symfony 1.4

I have created a collection form in symfony 1.4 and Propel 1.5 and everything displays properly but I cannot get the form to save to the database.
The form is used to edit multiple users at once.
I found this question and I implemented the suggestion of extending my collectionForm class with sfFormPropel, but when I do that I run out of memory. I cannot find what is being pulled from the database that would fill up the processes memory.
In my new save function I am not even doing anything.
Any ideas?
class ContactCollectionForm extends sfFormPropel
{
public function getModelName()
{
return 'ContactCollectionForm';
}
public function retrieveSubObject($fieldname, $model)
{
switch($fieldname)
{
default:
break;
}
return array();
}
public function save($con = null)
{
}
public function configure()
{
$user = $this->getOption('user');
$embedded = $this->getOption('embedded');
$custom = $this->getOption('custom');
$contact_list = $this->getOption('contact_list');
$cf = $custom['form'];
if(!array_key_exists(0, $cf['fields']['field']))
$cf['fields']['field'] = array($cf['fields']['field']);
$use_fields = array();
for($i=0;$i<count($contact_list);$i++)
{
foreach($cf['fields']['field'] as $field)
{
if($field['type'] == 'object')
{
// embed object form (ala: PersonData, Coordinate etc...)
$model = $field['model'];
$model_form = $model.'Form';
$sub_object = $contact_list[$i];
$sub_form = new $model_form($sub_object, array('user' => $user, 'embedded' => true, 'custom' => $field['fields']));
$this->embedForm($field['name'], $sub_form);
array_push($use_fields, $field['name']);
} // end field type == object
else
{
// standard form field
$this->setWidget($field['name'], CustomWidgetExtender::createSfWidget($field, $user, $this));
$this->widgetSchema->setLabel($field['name'], $field['label']);
if(trim($field['default']) != '')
$this->setDefault($field['name'], $field['default']);
// add field name to use_fields array
array_push($use_fields, $field['name']);
} // end field type != object
}
}
}
}
I ended up doing a rough hack by processing each form manually rather than trying to shoehorn this type of form into the symfony 1.x form framework.

Yii form model validation- either one is required

I have two fields on the form ( forgotpassword form ) username and email Id . User should enter one of them . I mean to retrieve the password user can enter user name or the email id . Could some one point me the validation rule for this ?
Is there any inbuilt rule I can use ?
( Sorry if it is already discussed or if I missed)
Thanks for your help
Regards
Kiran
I was trying to solve same problem today. What I've got is the code below.
public function rules()
{
return array(
// array('username, email', 'required'), // Remove these fields from required!!
array('email', 'email'),
array('username, email', 'my_equired'), // do it below any validation of username and email field
);
}
public function my_required($attribute_name, $params)
{
if (empty($this->username)
&& empty($this->email)
) {
$this->addError($attribute_name, Yii::t('user', 'At least 1 of the field must be filled up properly'));
return false;
}
return true;
}
General idea is to move 'required' validation to custom my_required() method which can check if any of field is filled up.
I see this post is from 2011 however I couldn't find any other solution for it. I Hope it will work for you or other in the future.
Enjoy.
Something like this is a bit more generic and can be reused.
public function rules() {
return array(
array('username','either','other'=>'email'),
);
}
public function either($attribute_name, $params)
{
$field1 = $this->getAttributeLabel($attribute_name);
$field2 = $this->getAttributeLabel($params['other']);
if (empty($this->$attribute_name) && empty($this->$params['other'])) {
$this->addError($attribute_name, Yii::t('user', "either {$field1} or {$field2} is required."));
return false;
}
return true;
}
Yii2
namespace common\components;
use yii\validators\Validator;
class EitherValidator extends Validator
{
/**
* #inheritdoc
*/
public function validateAttributes($model, $attributes = null)
{
$labels = [];
$values = [];
$attributes = $this->attributes;
foreach($attributes as $attribute) {
$labels[] = $model->getAttributeLabel($attribute);
if(!empty($model->$attribute)) {
$values[] = $model->$attribute;
}
}
if (empty($values)) {
$labels = '«' . implode('» or «', $labels) . '»';
foreach($attributes as $attribute) {
$this->addError($model, $attribute, "Fill {$labels}.");
}
return false;
}
return true;
}
}
in model:
public function rules()
{
return [
[['attribute1', 'attribute2', 'attribute3', ...], EitherValidator::className()],
];
}
I don't think there is a predefined rule that would work in that case, but it would be easy enough to define your own where for username and password fields the rule was "if empty($username . $password) { return error }" - you might want to check for a min length or other field-level requirements as well.
This works for me:
['clientGroupId', 'required', 'when' => function($model) {
return empty($model->clientId);
}, 'message' => 'Client group or client selection is required'],
You can use private property inside model class for preventing displays errors two times (do not assign error to model's attribute, but only add to model without specifying it):
class CustomModel extends CFormModel
{
public $username;
public $email;
private $_addOtherOneOfTwoValidationError = true;
public function rules()
{
return array(
array('username, email', 'requiredOneOfTwo'),
);
}
public function requiredOneOfTwo($attribute, $params)
{
if(empty($this->username) && empty($this->email))
{
// if error is not already added to model, add it!
if($this->_addOtherOneOfTwoValidationError)
{
$this->addErrors(array('Please enter your username or emailId.'));
// after first error adding, make error addition impossible
$this->_addOtherOneOfTwoValidationError = false;
}
return false;
}
return true;
}
}
don't forget "skipOnEmpty" attr. It cost me some hours.
protected function customRules()
{
return [
[['name', 'surname', 'phone'], 'compositeRequired', 'skipOnEmpty' => false,],
];
}
public function compositeRequired($attribute_name, $params)
{
if (empty($this->name)
&& empty($this->surname)
&& empty($this->phone)
) {
$this->addError($attribute_name, Yii::t('error', 'At least 1 of the field must be filled up properly'));
return false;
}
return true;
}
Yii 1
It can be optimized of course but may help someone
class OneOfThemRequiredValidator extends \CValidator
{
public function validateAttribute($object, $attribute)
{
$all_empty = true;
foreach($this->attributes as $_attribute) {
if (!$this->isEmpty($object->{$_attribute})) {
$all_empty = false;
break;
}
}
if ($all_empty) {
$message = "Either of the following attributes are required: ";
$attributes_labels = array_map(function($a) use ($object) {
return $object->getAttributeLabel($a);
}, $this->attributes);
$this->addError($object, $_attribute, $message . implode(',',
$attributes_labels));
}
}
}
yii1
public function rules(): array
{
return [
[
'id', // attribute for error
'requiredOneOf', // validator func
'id', // to params array
'name', // to params array
],
];
}
public function requiredOneOf($attribute, $params): void
{
$arr = array_filter($params, function ($key) {
return isset($this->$key);
});
if (empty($arr)) {
$this->addError(
$attribute,
Yii::t('yii', 'Required one of: [{attributes}]', [
'{attributes}' => implode(', ', $params),
])
);
}
}