Laravel Socialite - Avatar is to slow - laravel

I am using the Laravel 5.0 with the Socialite Library. Everything works fine except i am a little disappointment with the size of the avatar.
Is it possible to get a bigger avatar?

Looking at the source code of Socialite https://github.com/laravel/socialite/blob/2.0/src/Two/FacebookProvider.php
You can see at line 91 that the url for the avatar appends a static ?type=normal at the end. The Facebook graph API documentation says that you can request an avatar size using an ENUM or custom width/height so you can modify line 91 and append an ENUM or custom width/height like ?type=large
More details can be found in the Facebook graph API documentation.
However, this is only for the Facebook driver so you will need to dig in a similar fashion for other providers. If their APIs do not allow such freedom as in the case of Facebook then you will need to do with the avatar being returned.
Updated March 12, 2015
Do not customize the original Socialite package, fork the repository and then make the change. You can then plug your forked repository into your project and also send a pull request to the original author in case he thinks its worth having the functionality you have implemented. Also, your forked repository will not be updated/maintained as is the case with the original package. In case you choose to update to the new package, your changes will be lost.

Fix for Facebook / Google / Twitter Small Avatar Photo
I have created this helper method on my AuthController
public function getBigAvatar($user, $provider)
{
return ($provider == "google") ? $user->getAvatar()."0" : $user->avatar_original;
}
AND THIS IS HOW I CALL IT:
$user = Socialite::driver( $provider )->user();
$userPhoto = $this->getBigAvatar($user, $provider);
So Simple in case its Google, Well just append 0 to the end of the url and well get a 500px avatar. And for twitter and Facebook, The Providers already offers an avatar_original attribute as seen in
FacebookProvider.php
protected function mapUserToObject(array $user)
{
$avatarUrl = $this->graphUrl.'/'.$this->version.'/'.$user['id'].'/picture';
return (new User)->setRaw($user)->map([
'id' => $user['id'], 'nickname' => null, 'name' => isset($user['name']) ? $user['name'] : null,
'email' => isset($user['email']) ? $user['email'] : null, 'avatar' => $avatarUrl.'?type=normal',
'avatar_original' => $avatarUrl.'?width=1920',
]);
}
TwitterProvider.php
return $instance->map([
'id' => $user->uid, 'nickname' => $user->nickname,
'name' => $user->name, 'email' => $user->email, 'avatar' => $user->imageUrl,
'avatar_original' => str_replace('_normal', '', $user->imageUrl),
]);
Since Google does not map this, And gets a default 50px image, we simple change it to 500px with is great for avatar.
WORKED PERFECT FOR ME, LET ME KNOW IF IT HELPS YOU!

Just append your required size after the ?type=normal like this:
graph.facebook.com/v2.2/{user}/picture?type=normal &width=76&height=76
this will override the type=normal

For use original avatars size from Facebook and Google:
public function handleProviderCallback($provider){
$userData = Socialite::driver($provider)->user();
$user = new User;
...
Google:
$user->avatar = preg_replace('/\?sz=[\d]*$/', '', $userData->avatar);
Facebook:
$user->avatar = $userData->avatar_original;

here is another simpler way for the avatar
public function redirectToProvider($provider)
{
return Socialite::driver($provider)->redirect();
}
public function handleProviderCallback($provider)
{
$user = Socialite::driver($provider)->user();
// dd($user);
if ($user) {
$authUser = $this->findOrCreateUser($user, $provider);
Auth::login($authUser, true);
return redirect()->route('home');
}
return 'something went wrong';
}
private function findOrCreateUser($user, $provider)
{
$found = User::where('provider_id', $user->id)->first();
if ($found) {
return $found;
}
// so the default is G+, change according to your needs
$avatar = str_replace('?sz=50', '', $user->avatar);
if ($provider == 'facebook' || $provider == 'twitter') {
$avatar = $user->avatar_original;
}
return User::create([
'username' => $user->name,
'email' => $user->email,
'avatar' => $avatar,
'provider' => $provider,
'provider_id' => $user->id,
]);
}
this way u dont change ur code much and easier for maintenance ,
however for some reason the facebook avatar doesnt show up in my app , plz if anyone can help i would deeply appreciate it.
here is my the current fb avatar link i get
https://graph.facebook.com/v2.6/xxxxxxxxxxx/picture?width=1920
and the view
<img class="user-avatar" src="{{ $user->avatar }}" alt="user avatar">

Here is code I have came up with
if($file = $user->getAvatar()) {
if ($provider == 'google') {
$file = str_replace('?sz=50', '', $file);
} elseif ($provider == 'twitter') {
$file = str_replace('_normal', '', $file);
} elseif ($provider == 'facebook') {
$file = str_replace('type=normal', 'type=large', $file);
}
}
Happy coding everyone :)
This is basically just replacement or a part of avatar image URL so it would return the bigger one.
getAvatar() function return the image url, so I stored it in variable $file
And depending on the provider url structure is different, so for each provider you need to change image URL string accordingly
Google
remove '?sz=50' from image url string
Twitter
remove '_normal' from image url string
Facebook
replace 'type=normal' with 'type=large' in image url string

Related

How to edit picture on Coudinary with Laravel

Any Idea how to edit pictures on Cloudinary using Laravel API? I did a lot of searches, but I didn't find any references. The add worked successfully, but I didn't find a solution for the edit.
Add code
$user->user_image = Cloudinary::upload(
$request->file('user_image')->getRealPath(),
[
'folder' => 'Testing'
]
)->getSecurePath();
Attempt at updating picture
public function updatePicture(Request $request, $user_id)
{
$data = $request->validate([
'user_image' => '',
]);
$data = Cloudinary::upload(
$request->file('user_image')->getRealPath(),
[
'folder' => 'Testing'
]
)->getSecurePath();
User::where("user_id", $user_id)->update($data);
return response()->json([
'message' => 'Successfully updated Picture!',
'success' => true,
], 200);
}
For deleting, you can use the destroy() method of the API, for example:
$result = Cloudinary::destroy(
$public_id, //Public ID of the file from Cloudianry to delete - returned from the Upload API response
[
'...' => '...' //any optional parameters
]
)
For a list of all optional parameters and possible values please see:
https://cloudinary.com/documentation/image_upload_api_reference#destroy_method
In terms of updating, I am assuming you are referring to Cloudinary's update details of a single resource method of the Admin API. If so, you can access it like so:
$admin_api = Cloudinary::admin();
$result = $admin_api->update($public_id, $options = []);
Alternatively, if you're referring to the explicit method of the Upload API then you could access it like so:
$result = Cloudinary::explicit($public_id, $options = []);

How to get paymentMethodNonce in Braintree API?

I'm working in laravel 5.4
My transactions are successfull when I try a 'fake_nonce' type of string provided by the braintree docs. But when I tried to get the paymentMethodNonce it always gives me error like nonce not found. And sometimes http error!!! If I try to configure it by myself!
Take a look at my controller function below
public function addOrder(Request $request){
$customer = Braintree_Customer::create([
'firstName' => $request->guest_name,
'email' => $request->guest_email,
'phone' => $request->guest_phone
]);
$customer->success;
$customer->customer->id;
$find = Braintree_Customer::find($customer->customer->id);
$nonceFromTheClient = Braintree_PaymentMethodNonce::find($find);
$result = Braintree_Transaction::sale([
'amount' => $request->subtotal,
'paymentMethodNonce' => $nonceFromTheClient,
'options' => [
'submitForSettlement' => True
]
]);
if ($result->success) {
$settledTransaction = $result->transaction;
} else {
print_r($result->errors);
}
Cart::destroy();
return view('guest/track', compact('result'));
}
$nonceFromTheClient = Braintree_PaymentMethodNonce::find($find);
Your using the wrong nonce, this nonce must come from the DropIn ui and not be generated on your code.
Please check the onPaymentMethodReceived() method provided in the JS SDK.
Please check this reference

Laravel Simultaneously input one to many in database

I have a card, this card has tags. So a Card has many tags and a Tag belongsTo a Card.
A user fills a form. He gives both the information for the card aswell as the tags.
Now I need to give each tag the information 'card_id' so it can be connected.
Now is my problem that I don't know this 'card_id' yet because the database did not yet assign a id as they are both being created simultaneously.
My situation:
public function create(Request $request)
{
$this->validate($request,[
'function' => 'max:255',
'description' => 'max:255',
'rate' => 'max:255',
'location' => 'max:255'
]);
$card = new Card;
$card->user_id = Auth::id();;
$card->function = $request->function;
$card->description = $request->description;
$card->rate = $request->rate;
$card->location = $request->location;
// I also tried this: $card->tag()->saveMany($tagsArray); (Did not work)
$card->save();
$tagsArray = explode(',', $request->tagsarray);
foreach($tagsArray as $tagInput) {
$tag = new Tag;
$tag->card_id = 'Cant know this yet :(';
$tag->tag = $tagInput;
$tag->save();
}
return redirect('/page');
}
Does someone know how to go about this?
You may try something like this:
$card = new Card([
'card_name' => request()->get('card_name'),
'something_else' => request()->get('something_else')
]);
if($card->save()) {
$tags = [];
// Get the tag information from request
$tagsFromRequest[
['tag_title' => 'A Tag', 'tag_slug' => 'a_tag'],
['tag_title' => 'Another Tag', 'tag_slug' => 'another_tag']
];
foreach($tagsFromRequest as $tag) {
$tags[] = new Tag($tag);
}
$card->tags()->saveMany($tags);
}
Now, prepare your tags from request where each tag item should be an array as given above and I can't be more specific because you gave nothing that you've tried and which might help me to understand your scenario. Check the documentation.

How-to Form confirmation response

I am a Laravel newbie. I have gone through tutorials successfully...this is my first production app for a client, using Laravel
I have a form and am able to get the submitted data into a database. The user is given a generic error though. After successful submission, I cannot redirect the user to a confirmation page. Any help is appreciated.
Here is the code from my controller (the store function):
/**
* Store a newly created resource in storage.
*
* #return Response
*/
public function store()
{
$rules = array(
'lastname' => 'required',
'email' => 'required|email',
'phone' => 'required',
'date' => 'date|date_format:"m/d/Y"'
);
$validator = Validator::make(Input::all(), $rules);
// process the login
if ($validator->fails()) {
return Redirect::to('nerds/create')
->withErrors($validator)
->withInput(Input::except('password'));
}
else
{
// store
$registration = new Registration;
$registration->firstname = Input::get('firstname');
$registration->lastname = Input::get('lastname');
$registration->email = Input::get('email');
$registration->date = date("Y-m-d", strtotime(Input::get('date')));
$registration->phone = Input::get('phone');
$registration->venue = Input::get('venue');
$registration->venueCity = Input::get('venueCity');
$registration->save();
// redirect
Session::flash('message', 'Successfully submitted, someone will contact you soon!');
return Redirect::to('thankyou');
}
}
Please make sure the app/storage folder has the full permissions. Apache should be able to write to that folder.
There must be a route to handle the 'Redirect::to'
The tutorial I followed failed to mention this fact.
Along with the code from my controller's store() function, the following route is necessary.
Route::get('/registration/thankyou', function()
{
return View::make('thankyou');
});

Update profile function

I have a function that check updates the users profile info. Currently, if I put |unique:users in the validator every time I try to update the profile info on the form it will not let me because a user (which is me) has my email. So I figured out the unique means that nobody, including the current user can have the email that is being updated.
So I need to compare the current auth email to the one in the database. If it matches then it is ok to update the profile info. I know this is simple but I am not sure how to implement it and if that is the right logic.
So where in this code would I post if (Auth::user()->email == $email){..update email...} http://laravel.io/bin/GylBV#6 Also, is that the right way to do this?
public function editProfileFormSubmit()
{
$msg = 'Successfully Updated';
$user_id = Auth::id();
$user = User::find($user_id);
$first_name = Input::get('first_name');
$last_name = Input::get('last_name');
$email = Input::get('email');
$phone_number = Input::get('phone_number');
$validator = Validator::make(Input::all(), array(
'email' => 'required|email',
'first_name' => 'required',
'last_name' => 'required',
'phone_number' => 'required'
));
if ($validator->fails()) {
return Redirect::route('edit-profile')
->withErrors($validator)
->withInput();
}else{
if(Input::hasFile('picture')){
$picture = Input::file('picture');
$type = $picture->getClientMimeType();
$full_image = Auth::id().'.'.$picture->getClientOriginalExtension();
if($type == 'image/png' || $type == 'image/jpg' || $type == 'image/jpeg'){
$upload_success = $picture->move(base_path().'/images/persons/',
$full_image);
if($upload_success) {
$user->picture = $full_image;
} else {
$msg = 'Failed to upload picture.';
}
}else{
$msg = 'Incorrect image format.';
}
}
$user->first_name = $first_name;
$user->last_name = $last_name;
$user->email = $email;
$user->phone_number = $phone_number;
$user->save();
return Redirect::route('invite')->with('global', $msg);
}
}
Worry not, Laravel has already considered this potential issue! If you take a look at the docs for the unique validation rule you'll see that it can take some extra parameters. As it happens, you can give it an id to ignore when looking at the unique constraint. So what you need to do is work out the id for the current model to update and pass that in. In the case of updating a logged-in user's profile it's made easy by Auth::id() as you already have in your code.
$rules = [
'email' => ['required', 'email', 'unique:users,email,'.Auth::id()],
'first_name' => ['required'],
// etc...
];
Obviously I chose to use the array syntax for validation rules there, but you can do the same with the pip syntax too. In a less specific system (create-or-add in a crud postSave type action) you can still do it by simply dong something like $model = Post::find($id) and then if $model is null you're creating and you just use 'unique' whereas if $model is not null, use 'unique:table,field,'.$model->getKey().

Resources