Yii2 HTML purifier - yii2

I've got a question about Yii2's validation. So, my model validation rule's something like this:
return [
['status', 'required', 'on' => 'update'],
[['status'], function ($attribute) {
$this->$attribute = \yii\helpers\HtmlPurifier::process($this->$attribute);
}],
];
The problem is that if the content is <script>alert('something')</script>, it will be blank due to purifier and the content will pass the required validation.
So how can I revalidate the content for require? Or what is the good way to do it?

Validation rules are processed one after another so just put the second one as first.
return [
['status', 'filter', 'filter' => function ($value) {
return \yii\helpers\HtmlPurifier::process($value);
}],
['status', 'required', 'on' => 'update'],
];

Related

Yii2 Variables to be passed in URL - rules not working

I have two actions with parameters. I have written two url rules, but only one works at a time. I don't know the issue. These are my acions,
Index action in Site Controller and other one is index action in Product Controller
public function actionIndex($language = null) {
/* some codes */
}
public function actionIndex($id= null) {
/* some codes */
}
'rules' => [
'<language>' => 'site/index',
'<id>' => 'product/index',
]
The above are my url rules.But only the first rule is working. What is the issue?
Your rules are ambiguous. '<language>' pattern will match every URL, so second rule will never be reached. You should either create different URL structure for these two rules:
'rules' => [
'<language>' => 'site/index',
'id/<id>' => 'product/index',
],
Or use different patters (only literal languages and numerical IDs):
'rules' => [
'<language:[a-z]+>' => 'site/index',
'<id:\d+>' => 'product/index',
],

Yii2 : Require at least one of the two fields

One of the two phone numbers phone_parent or phone_students must be provided AND they must be an integer. When combined, only atLeastValidator works, when I leave it out, the integer works. Out of ideas. Any hint?
[['phone_parent', 'phone_student'], 'integer'],
['phone_student', AtLeastValidator::class, 'in' => ['phone_student', 'phone_parent']],
['phone_parent', AtLeastValidator::class, 'in' => ['phone_student', 'phone_parent']],
update: I've just discovered that integer works when I try to submit (no request is sent yet, I remain on form page); However it should work on focus out - just like all the other validators; It's an instance of ActiveForm.
I don't think you need to have that custom AtLeastValidator, you can use when and whenClient in the following way to work the way you want.
Your rules should look like below
[
['phone_parent'],
'required',
'when' => function ($model) {
return ($model->phone_student == '');
},
'whenClient' => 'function(attribute,value){
return ($("#testform-phone_student").val()=="");
}',
'message' => 'Either Parent or Student Phone must be filled',
],
[
['phone_student'],
'required',
'when' => function ($model) {
return ($model->phone_parent == '');
},
'whenClient' => 'function(attribute,value){
return ($("#testform-phone_parent").val()=="");
}',
'message' => 'Either Parent or Student Phone must be filled',
],
[['phone_parent', 'phone_student'], 'integer'],
Above all i would use a regular expression in order to validate the phone number to be valid rather than just using integer that will allow 0 as a pone number or mobile number which isnt valid. using match validator with a regex in the pattern will make it solid.

yii2 SluggableBehavior is applied to only emty slug field

I am using SluggableBehavior in such way
public function behaviors()
{
return [
[
'class' => SluggableBehavior::className(),
'attribute' => 'name',
'slugAttribute' => 'alias',
],
];
}
It works nice If field 'alias' in form is empty.
How to ignore this behaviors If field alias is not empty on form submitting ?
thanks in advance !
Add 'immutable'=>true in the behavour config.
The behaviour works in such way, that if the slugAttribute is not empty when immutable is on, that attribute will not be changed.
Try something like:
Configure this behavior with specific name:
return [
'slug' => [
'class' => SluggableBehavior::className(),
'attribute' => 'name',
'slugAttribute' => 'alias',
],
];
In controller load attributes from the form (before validation).
Check if alias attribute is empty.
If it is not - detach this behavior ($this->detachBehavior('slug')).
Validate model.

targetAttribute (Or something similar) for required validator (Yii2)

So, here is my scenario. I have got a model called URL. URL has the following attributes: link (required), scheme (required, but not safe.scheme is parsed from the link) and a few other attributes as well, which are not in context to this question.
Now, I made a custom validator for the scheme, which is following:
public function validateScheme($attribute, $param) {
if(empty($this->scheme)){
$this->addError('link', Yii::t('app', 'This is an invalid URL.'));
}
if (!in_array($this->scheme, $this->allowedSchemes)) {
$this->addError('link', Yii::t('app', 'This is an invalid URL.'));
}
}
Rules for URL:
public function rules() {
return [
['link', 'required', 'message' => Yii::t('app', 'URL can\'t be blank.')],
[['link'], 'safe'],
[['link'], 'string'],
['scheme', 'validateScheme']
];
}
This works fine when an invalid scheme is encountered, for example like let's say ftp.
However, when a completely invalid URL is entered, the scheme remains empty and the validateScheme is never triggered as, attribute scheme is not required. To verify, I called $model->validate() and it returns true even if it should not (or should may be, because the attribute is not required anyway).
So, my question number 2 : Is there a way to force the validateScheme be triggered no matter if the attribute is empty, or non empty? I do not seem to find a way to do this in documentation.
I then tried the other way around, and made scheme a required field. The problem with that is the fact that scheme field is not safe and not there in the form. So, the URL does not save, but no error is shown.
My question number 1, in that case would be: Is there a way to assign targetAttribute for scheme so that the error message is shown below link?
P.S. I know I can do this in the controller. I do not want to do that. I want to use the model only.
Another solution is, instead of having a default value, you could enable verify on empty (by default, it does not validate empty and not required fields). Something like this:
public function rules() {
return [
['link', 'required', 'message' => Yii::t('app', 'URL can\'t be blank.')],
[['link'], 'string'],
['scheme', 'validateScheme', 'skipOnEmpty' => false]
];
}
See more here.
Okay, setting a default value in the rules() solved my problem. The modified rules():
public function rules() {
return [
['link', 'required', 'message' => Yii::t('app', 'URL can\'t be blank.')],
[['link'], 'safe'],
[['link'], 'string'],
['scheme', 'default', 'value' => 0],
['scheme', 'validateScheme']
];
}

Handle Image update in yii2

Hi everyone i am using FileInput kartik widget in yii2 project and uploading and saving works fine but i am having problem while updating the images
I can get the images path on the update form and create and array and display in as initialpreview in the widget but the problem is that my files field is required field so even there are some values in initialpreview the form gives error to upload image as its required field. So what should i do here?
I only want to give preview of their uploaded pics to the user but if they dont make any changes than i dont want to update anything for images
Following is my view code and model code
return [
[[ 'price', 'created_date', 'created_by', 'updated_date', 'updated_by','file','address'], 'required'],
[['price'], 'number'],
[['address'], 'string', 'max' => 255],
[['file'], 'file', 'extensions'=>'jpg, gif, png', 'maxFiles' => 4],
];
<?php
$initalpreview = array();
foreach($model->adsImages as $images) {
$initalpreview[] = Html::img('/upload/'.$images->image, ['class'=>'file-preview-image']);
}
?>
<?=$form->field($model, 'file[]')->widget(FileInput::classname(), [
'options' => ['accept' => 'image/*',
'multiple'=>true],
'pluginOptions' => [
'maxFileCount' => 5,
'initialPreview'=> $initalpreview,
'showUpload' => false,
]
]); ?>
So what should i do here?
Thank you
try this
In Model create a scenario named 'update' and mention the fields that are required when update action works
return [
[['price', 'created_date', 'created_by','updated_date','updated_by','address'], 'required', 'on' => 'update'],
];
Now inside controller action update call the scenario
public function actionUpdate(){
//Model Declaration
$model->scenario = 'update';
// update code
}