How to assert mockery shouldReceive - laravel

I'm trying to implement middleware unit test using Mockery
public function handle() {
// create user
$user = factory(User::class)->create();
// log in as admin user
$this->be($user, 'api');
$response = \Mockery::mock('Illuminate\Http\JsonResponse')->shouldReceive('getContent', 'setData')->once()->andReturn(json_encode(['data' => [], 'meta' => []]))->getMock();
$request = Request::create('/admin/customers', 'GET');
$middlewareResponse = $this->middleware->handle($request, function () use ($response) {
return $response;
});
print_r($middlewareResponse); exit;
}
How can I get setData and perform assertion?
here is the middlewareResponse
[_mockery_receivedMethodCalls:protected] => Mockery\ReceivedMethodCalls Object
(
[methodCalls:Mockery\ReceivedMethodCalls:private] => Array
(
[0] => Mockery\MethodCall Object
(
[method:Mockery\MethodCall:private] => getContent
[args:Mockery\MethodCall:private] => Array
(
)
)
[1] => Mockery\MethodCall Object
(
[method:Mockery\MethodCall:private] => setData
[args:Mockery\MethodCall:private] => Array
(
[0] => Array
(
[data] => Array
(
)
[meta] => Array
(
[home] => /customer/test/dashboard/consectetur-architecto-nostrum
)
)
)
)
)
)
Here is my HomePage middleware
class HomePage
{
/**
* Handle an incoming request.
*
* #param Request $request
* #param Closure $next
* #return mixed
*/
public function handle($request, Closure $next) {
// get original response
$response = $next($request);
$responseData = json_decode($response->getContent(), true);
$data['meta'] = [
'home' => null,
];
//print_r($response);exit;
if($response instanceof JsonResponse) {
// get banner meta data
$data['meta'] = $this->getHomePageUrl();
}
// merge meta data into original
$payloadWithMeta = array_merge_recursive($responseData, $data);
$response->setData($payloadWithMeta);
return $response;
}
/**
* generate dashboard url for user's first customer of first profile
*
* #return array
*/
private function getHomePageUrl() {
// first initialise an empty profile
$profile = null;
// fetch user's first customer
$user = Auth::user();
$customer = $user->customers()->orderBy('title')->first();
// set profile if customer found
if($customer) {
$customer->activateDatabase();
$profile = Profile::orderBy('title')->first();
}
return [
'home' => $profile ? 'customer/settings' : null
];
}
}
``

Related

Observer not running when creating in database

Hello I have this method that mass create student sections
Enrollment controller method this code works fine but it doesn't get in my studentSectionObserver. Although it's getting saved one by one with for loop.
public function setStudentsSection(Request $request)
{
$enrollments = Enrollment::whereIn('student_id', $request->students)->where('session_id', $request->session_id)->get();
$program_section = ProgramSection::withCount('students')->find($request->program_section_id);
if(($program_section->students_count + count($enrollments)) <= $program_section->max_students) {
$new_student_sections = array();
foreach($enrollments as $enrollment) {
$data = [
'student_id' => $enrollment->student_id,
'enrollment_id' => $enrollment->id,
'section_id' => $request->program_section_id,
'created_at' => Carbon::now()
];
array_push($new_student_sections, $data);
}
return StudentSection::insert($new_student_sections);
}
return response()->json(['errors' => ['message' => 'Selected Section is full.']], 405);
}
Then i output this activity with studentSectionObserver and added log::info but it doesn't log anything
public function created(StudentSection $student_section)
{
Log::info('test');
$student = $student_section->student()->get()->first();
$section = $student_section->section()->get()->first();
Logger::createLog("Assigned " . $student->first_name . " " . $student->last_name . " '" . $section->section->name . "'");
}
I know this observer gets triggered cause i tested it with this method whenever i add section the studentSectionObserver triggers Logger.
public function enrollStudent(EnrollmentRequest $request)
{
$check_if_exist = Enrollment::where('student_id', $request->student_id)->where('session_id', $request->session_id)->first();
if (!$check_if_exist) {
$program_section = ProgramSection::withCount('students')->find($request->section_id);
if($program_section) {
if($program_section->students_count < $program_section->max_students) {
$enrollment = Enrollment::create($request->all());
$section_data = ['student_id' => $request->student_id, 'section_id' => $request->section_id, 'enrollment_id' => $enrollment->id];
$section = StudentSection::create($section_data);
return response()->json($enrollment, 200);
}
return response()->json(['errors' => ['message' => 'Selected Section is full.']], 405);
}
$enrollment = Enrollment::create($request->all());
return response()->json($enrollment, 200);
}
return response()->json(['errors' => ['message' => 'Student is already enrolled in this session.']], 405);
}
Any help would be greatly appreciated.
As you have figured out the answer on your own.
The reason for using create method is because it triggers the event on the model. Same goes for update method.
Following is the update method under the hood:
/**
* Update the model in the database.
*
* #param array $attributes
* #param array $options
* #return bool
*/
public function update(array $attributes = [], array $options = [])
{
if (! $this->exists) {
return false;
}
return $this->fill($attributes)->save($options);
}
And the save method has these lines of code:
if ($this->fireModelEvent('saving') === false) {
return false;
}
Similarly, create method works. That's why insert doesn't trigger the event on model and you had to use create method.
Turns out i just need to use create method.
public function setStudentsSection(Request $request)
{
$enrollments = Enrollment::whereIn('student_id', $request->students)->where('session_id', $request->session_id)->get();
$program_section = ProgramSection::withCount('students')->find($request->program_section_id);
if(($program_section->students_count + count($enrollments)) <= $program_section->max_students) {
foreach($enrollments as $enrollment) {
$response = StudentSection::create([
'student_id' => $enrollment->student_id,
'enrollment_id' => $enrollment->id,
'section_id' => $request->program_section_id,
'created_at' => Carbon::now()
]);
return $response;
}
}
return response()->json(['errors' => ['message' => 'Selected Section is full.']], 405);
}
Laravel observer doesn't work on bulk objects, it only works with single object.
So when you use create() function it will trigger the observer.

Create flash message in class request laravel

i have a problem in my project. How to create a flash session in class request / validation ? I haven't found a way.
This my Request class code
class UserRequest extends FormRequest {
public function authorize()
{
return TRUE;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
$rules = [
"user_fullname" => "required|alpha_spaces",
"user_email" => "required|email|unique,list_user,user_email",
"user_phone" => "nullable|numeric",
"access_id" => "required|alpha_num_spaces",
"user_password" => "required|min:6|regex:/^.*(?=.{3,})(?=.*[a-zA-Z])(?=.*[0-9]).*$/|confirmed",
"warehouse_id" => "alpha_num_spaces|nullable",
];
if ($this->method() == "POST") {
$rules["province_id"] = "alpha_num_spaces|nullable";
$rules["district_id"] = "alpha_num_spaces|nullable";
$rules["subdistrict_id"] = "alpha_num_spaces|nullable";
$rules["kode_pos"] = "alpha_num_spaces|nullable";
$rules["user_address"] = "alpha_num_spaces|nullable";
}
return $rules;
}
public function messages()
{
return [
"user_password.regex" => "Password wajib terdiri dari huruf & angka!"
];
}
}
This my controller
public function process_user_add(UserRequest $user_request)
{
$user_request->validated();
$request = \request();
$input = (object) \request()->all();
$check = User::add_user_from_owner($input);
if ($check->success) {
return \redirect()->to("administrator/user/" . \encrypt_url($check->id))->with("message", "<script>sweet('success', 'Success!', '$check->message')</script>");
} else {
return \redirect()->back()->with("message", "<script>sweet(\"error\", \"Failed!\", \"$check->message\")</script>")->withInput($request->all());
}
}
How to i check if validation failed, i create a flash message? To my knowledge, class request is auto redirect goback url if validation error
You can use die Validator Facade. Validator::make() After then you can rescieve the fails with the fails() Method. Take a look in the code below:
$rules = array(
"user_fullname" => "required|alpha_spaces",
"user_email" => "required|email|unique,list_user,user_email",
"user_phone" => "nullable|numeric",
"access_id" => "required|alpha_num_spaces",
"user_password" => "required|min:6|regex:/^.*(?=.{3,})(?=.*[a-zA-Z])(?=.*[0-9]).*$/|confirmed",
"warehouse_id" => "alpha_num_spaces|nullable",
);
$validator = Validator::make($request->all(), $rules);
if ($validator->fails())
{
return Redirect::to('/your_url')->withInput()->withErrors($validator);
}
This section from the documentation will point you to the right direction

updating record in yii2 with condition but not working

<?php
namespace frontend\controllers;
use Yii;
use common\models\Subscriber;
use common\models\SubscriberSearch;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
/**
* SubscriberController implements the CRUD actions for Subscriber model.
*/
class SubscriberController extends Controller
{
/**
* Creates a new Subscriber model.
* If creation is successful, the browser will be redirected to the 'view' page.
* #return mixed
*/
public function actionSubscribe()
{
$model = new Subscriber();
if ($model->load(Yii::$app->request->post()) && $model->validate()) {
if ($model->sendEmail()) {
Yii::$app->session->setFlash('success', 'You have successfully subscribed My-Blog. You will get notification whenever New post is published');
return $this->goHome();
} else {
Yii::$app->session->setFlash('error', 'Sorry, we are unable to subscribe for the provided email address.');
}
}
return $this->render('create', [
'model' => $model,
]);
}
/**
* Finds the Subscriber model based on its primary key value.
* If the model is not found, a 404 HTTP exception will be thrown.
* #param integer $id
* #return Subscriber the loaded model
* #throws NotFoundHttpException if the model cannot be found
*/`enter code here`
}
using following model :
<?php
namespace common\models;
use Yii;
use yii\behaviors\TimestampBehavior;
use yii\db\ActiveRecord;
use yii\db\Expression;
/**
* This is the model class for table "subscriber".
*
* #property int $id
* #property string $email
* #property string $token
* #property int $status
* #property int $created_at
* #property int $updated_at
*/
class Subscriber extends \yii\db\ActiveRecord
{
const STATUS_DEACTIVE = 0;
const STATUS_ACTIVE = 1;
/**
* #inheritdoc
*/
public static function tableName()
{
return 'subscriber';
}
public function behaviors()
{
return [
'timestamp' => [
'class' => TimestampBehavior::className(),
'attributes' => [
ActiveRecord::EVENT_BEFORE_INSERT => ['created_at', 'updated_at'],
ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'],
],
'value' => new Expression('NOW()'),
],
];
}
/**
* #inheritdoc
*/
public function rules()
{
return [
[['email'], 'required'],
[['status', 'created_at', 'updated_at'], 'integer'],
[['email'], 'string', 'max' => 60],
[['token'], 'string', 'max' => 255],
[['token'], 'unique'],
[['email'], 'unique', 'targetClass' => '\common\models\Subscriber', 'message' => 'This email has already subscribed our blog.','filter' => ['!=','status' ,0]],
];
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'email' => 'Email',
'token' => 'Token',
'status' => 'Status',
'created_at' => 'Created At',
'updated_at' => 'Updated At',
];
}
/**
* Generates subscriber token
*/
public function generateSubscriberToken()
{
return $this->token = Yii::$app->security->generateRandomString() . '_' . time();
}
/**
* Send Email when successfully subscribe
*/
public function sendEmail()
{
$subscribers = Subscriber::find()->where(['email' => $this->email, 'status' => 0,])->one();
if(!$subscribers)
{
$this->generateSubscriberToken();
if(!$this->save())
{
return false;
}
return Yii::$app->mailer
->compose()
->setFrom(['noreply#my-blog.com' => Yii::$app->name . ' robot'])
->setTo('piyush#localhost')
->setSubject('Subscription : ' . Yii::$app->name)
->setHtmlBody('Thank you '.$this->email.' for subscribing '.Yii::$app->name.'<br /><br /> You will receive notification whenever new trick or post is published to website')
->send();
}
$subscribers->generateSubscriberToken();
$subscribers->status = 1;
if(!$subscribers->save())
{
return false;
}
return Yii::$app->mailer
->compose()
->setFrom(['noreply#my-blog.com' => Yii::$app->name . ' robot'])
->setTo('piyush#localhost')
->setSubject('Subscription : ' . Yii::$app->name)
->setHtmlBody('Welcome back '.$this->email.'Thank you for subscribing '.Yii::$app->name.'<br /><br /> You will receive notification whenever new trick or post is published to website')
->send();
}
}
This controller and model are being used to make subscribe activity using email. I want that IF a user has unsubscribed and after some time again want to subscribe then update status = 1 and regenerate token. Above sendEmail is working fine if it's a new subscriber but if it is an old subscriber with status 0 then not working.
Above all, you need to replace the lines
$subscribers->generateSubscriberToken();
$subscribers->status = 1;
with
$subscriber->token =$this->generateSubscriberToken();
$subscribers->status = 1;
as in your function you are setting $this->token and returning it and to update the record you need to set the $subcribers->token filed with the value.
And you should not search the table for the email with status 0 just query the email and check in PHP if status ==0 because a new record should only be entered if the email does not exist, without caring what the status field has so in your case if the email exists but with status =1 your query won't fetch the record and it will try to insert a record instead of doing nothing.
To understand you can try using var_dump(!$subscribers) in both cases an see what it returns.
Moreover, you are repeating things like sending email and token generation you should change your function to the below.
public function sendEmail()
{
$subscribers = self::find()->where(['email' => $this->email])->one();
//set flag for sending email
$sendMail = false;
//email subject
$subject = '';
//generate token
$token = $this->generateSubscriberToken();
//if email found in subscribers
if ($subscribers !== null) {
//check if inactive
if ($subscribers->status !== self::STATUS_ACTIVE) {
//assign token
$subscribers->token = $token;
//set status to active
$subscribers->status = self::STATUS_ACTIVE;
//update the recrod
if (!$subscribers->save()) {
return false;
}
//set subject
$subject = 'Welcome back ' . $this->email . 'Thank you for subscribing ' . Yii::$app->name . '<br /><br /> You will receive notification whenever new trick or post is published to website';
$sendMail = true;
}
} else { //if email does not exist only then insert a new record
$this->status = 1;
if (!$this->save()) {
return false;
}
$subject = 'Thank you ' . $this->email . ' for subscribing ' . Yii::$app->name . '<br /><br /> You will receive notification whenever new trick or post is published to website';
$sendMail = true;
}
//check if send mail flag set
if ($sendMail) {
return Yii::$app->mailer
->compose()
->setFrom(['noreply#my-blog.com' => Yii::$app->name . ' robot'])
->setTo('piyush#localhost')
->setSubject('Subscription : ' . Yii::$app->name)
->setHtmlBody($subject)
->send();
}
}

Symfony3 error changing DateTime on entity with Ajax

I want to change the date of a doctrine entity but the change is not saved.
With ajax a call this function:
public function relancerTicketAction(Request $request, $id)
{
if (!$this->get('session')->get('compte'))
return $this->redirect($this->generateUrl('accueil'));
$isAjax = $request->isXMLHttpRequest();
if ($isAjax)
{
$ticket = $this->getDoctrine()->getManager()->getRepository('CommonBundle:Ticket')->find($id);
$ticket->setDateButoire($ticket->getDateButoire()->modify('+7 day'));
$this->getDoctrine()->getManager()->flush();
$response = array("code" => 100, "success" => true, 'date' => $ticket->getDateButoire()->format('d-m-Y'));
return new Response(json_encode($response));
}
$response = array("code" => 0, "success" => false);
return new Response(json_encode($response));
}
When I alert the result I get the right new value, but after reload there is no change saved.
This function called in the same conditions works:
public function traiterTicketAction(Request $request, $id)
{
if (!$this->get('session')->get('compte'))
return $this->redirect($this->generateUrl('accueil'));
$isAjax = $request->isXMLHttpRequest();
if ($isAjax)
{
$compte = $this->getDoctrine()->getManager()->getRepository('CommonBundle:Compte')->find($this->get('session')->get('compte')->getId());
$ticket = $this->getDoctrine()->getManager()->getRepository('CommonBundle:Ticket')->find($id);
$ticket->addDestinataire($compte);
$this->getDoctrine()->getManager()->flush();
$response = array("code" => 100, "success" => true);
return new Response(json_encode($response));
}
$response = array("code" => 0, "success" => false);
return new Response(json_encode($response));
}
see the docs
When calling EntityManager#flush() Doctrine computes the changesets of
all the currently managed entities and saves the differences to the
database. In case of object properties (#Column(type=”datetime”) or
#Column(type=”object”)) these comparisons are always made BY
REFERENCE. That means the following change will NOT be saved into the
database:
/** #Entity */
class Article
{
/** #Column(type="datetime") */
private $updated;
public function setUpdated()
{
// will NOT be saved in the database
$this->updated->modify("now");
}
}
So, in your case I suggest to clone dateButoire, like this
$ticket = $this->getDoctrine()->getManager()->getRepository('CommonBundle:Ticket')->find($id);
$newDateButoire = clone $ticket->getDateButoire();
$ticket->setDateButoire($newDateButoire->modify('+7 day'));
$this->getDoctrine()->getManager()->flush();

how to get facebook email id from Nodge/yii2-eauth

Am trying to integrate Yii2 EAuth for facebook login integration.
I made configaration * in model am using below code
public static function findIdentity($id) {
if (Yii::$app->getSession()->has('user-'.$id)) {
return new self(Yii::$app->getSession()->get('user-'.$id));
}
else {
return isset(self::$users[$id]) ? new self(self::$users[$id]) : null;
}
}
/**
* #param \nodge\eauth\ServiceBase $service
* #return User
* #throws ErrorException
*/
public function findByEAuth($service) {
if (!$service->getIsAuthenticated()) {
throw new ErrorException('EAuth user should be authenticated before creating identity.');
}
$id = $service->getServiceName().'-'.$service->getId();
// echo $id;exit;
print_r($service->getAttribute('email'));
echo '<pre>';
print_r($service->getAttributes());
exit;
$attributes = array(
'id' => $id,
'username' => $service->getAttribute('name'),
'authKey' => md5(#$id),
'profile' => $service->getAttributes(),
);
$attributes['profile']['service'] = $service->getServiceName();
Yii::$app->getSession()->set('user-'.$id, $attributes);
return new self($attributes);
}
i want email , pls can any one help me to get facebook email id...thanks in advance......
I managed to get the email of the user from facebook after changing the few setting in vendor\nodge\yii2-eauth\src\services\FacebookOAuth2Service.php.
Edit FacebookOAuth2Service.php
Override protected $scopes = array(self::SCOPE_EMAIL);
And modify the fetchAttributes() functions. It should look like this:
protected function fetchAttributes()
{
$info = $this->makeSignedRequest('me');
$this->attributes['id'] = $info['id'];
$this->attributes['name'] = $info['name'];
$this->attributes['url'] = $info['link'];
$this->attributes['email'] = $info['email'];
return true;
}
Try and see it it works for you.

Resources