Assert File not validating - php

I have followed the instructions on the documentation for how to handle file upload using Doctrine.
Image upload works fine but when I upload some other file type, it just lets the file upload even if I have properly set the annotation on the $file property like this:
/**
* #Assert\File(
* maxSizeMessage = "L'image ne doit pas dépasser 5Mb.",
* maxSize = "5000k",
* mimeTypes = {"image/jpg", "image/jpeg", "image/gif", "image/png"},
* mimeTypesMessage = "Les images doivent être au format JPG, GIF ou PNG."
* )
*/
public $file;

I just figured out that the problem was coming from the Product entity. I was adding multiple images to a Product form and I forgot to put the Valid assert to the $images property on the Product entity like so :
/**
* #ORM\ManyToMany(targetEntity="PS\StockBundle\Entity\Image", cascade={"persist"})
* #Assert\Valid()
*/
private $images;
I wrote an article on my blog about this here https://web.archive.org/web/20141004165731/http://www.ennazk.com:80/validate-subforms-in-symfony2/#.Wdt9mBNSwnU
Thanks.

Is {"image/jpg", "image/jpeg", "image/gif", "image/png"}, valid json? because that does not look like a valid json for me (objects in json consist of key=>value pairs.). If json decode fails, then it is possible the entire assertion does not get applied. I don;t know that much about doctrine though, so i might be wrong.

Related

How to set #SWG\Info annotation for only area in Symfony using NelmioApiDocBundle

/**
* #SWG\Swagger(
* #SWG\Info(
* title="My first swagger documented API",
* version="1.0.0"
* )
* )
*/
I tried to write this block in:
my base controller - src/MyProject/ApiBundle/Controller/SiteApi/SiteApiBaseController.php
my bundle file - src/MyProject/ApiBundle/MyProjectApiBundle.php
Generated JSON contains empty "info": {"title": ""}
Symfony 3.4, NelmioApiDocBundle 3.9.1(including zircote/swagger-php 2.0.9)
• For controller try:
/**
use FOS\RestBundle\Controller\Annotations as Rest;
use Swagger\Annotations as SWG;
...
* Add Tva.
* #Rest\Post("/tva/add")
* #SWG\Tag(name="TVA Management")
...
...
* #SWG\Response(response=201, description="Tva created successfully.")
...
...
*/
=> You will get something like this:
• For api/doc page Title, Description & Version, try to edit this file:
~Your_Project_Path\config\packages\nelmio_api_doc.yaml

Laravel custom attribute in Model for Scaling image using Cloudinary URL

In my web app I am using Cloudinary for image storing. Image uploading is working properly but i want to create a custom attribute for image so when getting back the image url from the database with some modification with width and height.
The link of a image: https://res.cloudinary.com/wokong/image/upload/v1568570430/storyHeader/cxjir4g9tkaa8xepxodg.jpg
which is stored in database but when it fetch from the database, It should come with some scaling so that It wont take much time for website loading.
here is my StoryModel:
class Story extends Model
{
use Commentable, Searchable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'title',
'summary',
'content',
'created_at',
'story_statuses_id',
'image', 'language',
'likes',
'views',
'url_key',
];
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'is_public' => 'boolean',
];
I dont understand how to use it anyone can help?
Cloudinary supports runtime image resizing
As per their documentation instead of this
https://res.cloudinary.com/wokong/image/upload/v1568570430/storyHeader/cxjir4g9tkaa8xepxodg.jpg
use
https://res.cloudinary.com/wokong/image/upload/w_100,h_100,c_fit/v1568570430/storyHeader/cxjir4g9tkaa8xepxodg.jpg
As you can see, i have added /w_100,h_100,c_fit/ after upload to instruct Cloudinary to do the resizing on the fly
w is for width, h is for height and c is for scale type to be used while cropping
You can find the documentation here
UPDATE 1
Something like this should do it
$default_url = "https://res.cloudinary.com/wokong/image/upload/v1568570430/storyHeader/cxjir4g9tkaa8xepxodg.jpg";
$width = 100;
$height = 100;
echo str_replace("/upload", "/upload/w_".$width.",h_".$height.",c_fit", $default_url);
UPDATE 2
Your model will look like
class Story extends Model
{
use Commentable, Searchable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'title',
'summary',
'content',
'created_at',
'story_statuses_id',
'image', 'language',
'likes',
'views',
'url_key',
];
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'is_public' => 'boolean',
];
public function getImageForWebAttribute()
{
$width = 100; // You can keep this info in app config
$height = 100;
// Here i am assuming `image` is where you store Cloudinary url
return str_replace("/upload", "/upload/w_".$width.",h_".$height.",c_fit", $this->image);
}
}
and you can call it like
$story->image_for_web
Documentation for laravel custom mutators can be found here
Instead of saving the whole URL of the uploaded image in your database, you can save the public_id returned in the upload response.
Then you can just use Cloudinary's SDK to generate the transformation URLs for you, by passing the desired transformation parameters to the cloudinary_url() Helper function, along with the image's public_id.
For example, let's assume that you want to generate a URL of an image which its public_id is sample. In addition, you want that the image will be delivered with the best format possible, based on the client's device and browser. You would also like to use Cloudinary's automatic quality algorithm and scale the image down to a width of 500px while retaining its original aspect ratio.
You can achieve it by using the following code:
$url = cloudinary_url('sample', array(
'fetch_format' => 'auto',
'quality' => 'auto',
'crop' => 'scale',
'width' => 500
));
echo $url; will print the following:
http://res.cloudinary.com/<cloud_name>/image/upload/c_scale,f_auto,q_auto,w_500/sample
If you wish to generate the whole <img> tag using the SDK, you can utilize cl_image_tag() as an alternative to the URL only output of cloudinary_url().
Here's the link to the relevant section in Cloudinary's documentation with some more examples on how to use both cl_image_tag() and cloudinary_url().
Okay just an additional help for ...
Say for instance you attached $images to a view from the controller in laravel
you could generate fixed width and height on the fly via the url and attach to bootstrap grid system..
`
<div class="col-6 col-md-4 col-lg-3">
<a href="{{$image->image_url}}">
#php
$url = $image->image_url;
#endphp
<img class="img img-fluid" src="{{ str_replace("/upload", "/upload/w_350,h_220,q_70,c_scale", $url) }}" alt="">
</a>
</div>
`
You could also set this attributes of the image via the controller method using
Cloudder::show(Cloudder::getPublicId(), ["width" => $width, "height"=>$height])

Internal error due to serialization with paramconverter

I have an API which takes multiple input values. One of them is a date.
When the date is sent, all is fine.
But, when the user isn't sending a date, I have an error 500 with this error message:
Invalid datetime "Some invalid data", expected format Y-m-d\TH:i:sP.
So I wanted to check if the data sent had the format required.
But I don't understand how things are working, hope you can help.
This is what I have
/**
*
* #Rest\Post(
* path = "/signup",
* name = "api_users_add"
* )
* #Rest\View(StatusCode=201, serializerGroups={"user_detail"})
* #ParamConverter(
* "user",
* converter="fos_rest.request_body",
* options={"deserializationContent"={"groups"={"Deserialize"}}},
* )
* #ParamConverter(
* "profile",
* converter="fos_rest.request_body",
* options={"deserializationContent"={"groups"={"Deserialize"}}},
* )
*/
public function postUserAction(Request $request, User $user, Profile $profile)
{
if (!preg_match("^[0-9]{4}-[0-1][0-9]-[0-3][0-9]$",$profile->getBirth())){
return new JsonResponse([
'success' => false,
'message' => "Date d'anniversaire au mauvais format"
]);
}
}
But in fact, I never go into this condition, the error 500 is triggered before.
I guess this has something to do with the #ParamConverter from Profile who can't "deserialize" when birth is not a DateTime.
Thing is, I would like to check what is sent (as I did into my condition) in order to avoid this internal error. But I can't find where this is handled on my code.
Thanks for the help.
Considering this : symfony doc for Param converter fos rest bundle
What I am looking for is to find where the validationErrors are specified.

Symfony validation on multiple file upload

I have a form containing a FileType field. I've set the multiple option to true so the user can upload multiple files at the same time.
$builder->add('myFile', FileType::class, [
'label' => 'upload file',
'multiple' => true,
])
Here is the corresponding property in the Entity connected to this form:
/**
* #Assert\NotBlank()
* #Assert\File(mimeTypes = {"application/pdf", "application/x-pdf", "image/jpeg", "image/png"})
* #ORM\Column(type="array")
*/
private $myFile;
When I submit the form I get the error:
UnexpectedTypeException in FileValidator.php line 168:
Expected argument of type "string", "array" given
I added curly braces in front of File assert so it looks like this:
* #Assert\File{}(mimeTypes = {"application/pdf", "application/x-pdf", "image/jpeg", "image/png"})
Now it doesn't complain when submitting the form. but the file type validation is also not checked.
Any idea how to make the file type working for multiple selected files?
Since you're validating array of File, you need to apply All validator, which will apply inner validators on each element of the array.
Try with something like:
/**
* #Assert\All({
* #Assert\NotBlank(),
* #Assert\File(mimeTypes = {"application/pdf", "application/x-pdf", "image/jpeg", "image/png"})
* })
* #ORM\Column(type="array")
*/
private $myFile;

Custom validaton messages not working on Symfony 3

I have the following declaration in my user class (Symfony 3, it's an entity class):
/**
* #ORM\Column(type="string", length=128, unique=true)
* #Assert\NotBlank (
* groups={"registration"},
* message = "test"
* )
* #Assert\Email(
* message = "The email '{{ value }}' is not a valid email.",
* groups={"registration"}
* )
*/
private $email;
Everything works fine, except that I can't set a message, instead of my message ('test' for example) a default "This value should not be blank" is displayed.
Yes, I do have
framework:
validation: { enable_annotations: true }
In my config.yml
Edit: and yes I cleared cache by executing:
sudo php bin/console cache:clear
Edit2: Please note that it actually DOES go through validation, Symfony sees that the email is required, it displays a message if I leave the field empty, it's just that it is not my message, Symfony somehow doesn't see the "message" part.
Edit3: Now, after removing the groups={"registration"} part, as well as changing (in controller)
$errors = $validator->validate($user, null, array('registration'));
to
$errors = $validator->validate($user, null);
(removed array('registration'))
the correct message is displayed. However this is not a solution. I need to use groups.
Edit 4:
I'll get crazy...
If I enter no email, and then:
$validator = $this->get('validator');
$errors = $validator->validate($user, null, array('registration'));
dump($errors);
(Notice the "dump" function call) then I see an incorect message displayed on a page (This value should not be blank) but... when I enter the profiler->debug page (the dev tools at the bottom) then I can see that a correct (my) message is there...
Furthermore in profiler->form errors is this incorect message on the list (as only one item) but... it says it refers to a field named "plainPassword" which is not in the form, and does NOT belong to the "registration" group, so it should not be validated in the first place.
What's going on there?
Can You try this?
/**
* #ORM\Column(type="string", length=128, unique=true)
*
*
* #Assert\NotBlank(
* message = "The box cant be left blank")
*
*
* #Assert\Email(
* message = "The email '{{ value }}' is not a valid email."
*
* )
*/
private $email;

Categories