cakephp 4 redirect user in EventListener - cakephp

I have an UserEventListener which implements EventListenerInterface.
In the event: afterLogin($event){} I would like to redirect the user if the profile is not complete, I can't figure out how to do redirect with the $event parameter
Edit:
here is the code of the UserEventListener:
<?php
namespace App\Event;
use Authentication\AuthenticationService;
use Authentication\AuthenticationServiceInterface;
use Authentication\AuthenticationServiceProviderInterface;
use Authentication\Middleware\AuthenticationMiddleware;
use Psr\Http\Message\ServerRequestInterface;
use Cake\Event\EventListenerInterface;
use Cake\Datasource\FactoryLocator;
use Cake\Log\Log;
class UserEventListener implements EventListenerInterface
{
public function implementedEvents(): array
{
return [
'Users.Authentication.afterLogin' => 'afterLogin',
//'Users.Authentication.afterLogout' => 'afterLogout'
];
}
public function afterLogin($event)
{
$profilesTable = FactoryLocator::get('Table')->get('Profiles');
$profiles = $profilesTable->find()
->where(['user_id' => $event->getData('user')->id])
->order(['id' => 'DESC'])->toList();
if((count($profiles) == 1) && $profiles[0]->mobile == "" ){
//-- here I would like to redirect --------
//return $event->getSubject()->redirect(['Controller'=>'Profiles', 'action' => 'edit',$event->getData('user')->id]);
}
}
}

Related

CakePHP3 - Cookie Value not being kept

I have a problem where the value for the cookie I set is not being kept if switching to a different section (controller) with CakePHP3.
I establish the original cookie in the AppController so it is sitewide:
<?php
namespace App\Controller;
use Cake\Controller\Controller;
use Cake\Event\Event;
use Cake\Http\Cookie\Cookie;
use Cake\Http\Cookie\CookieCollection;
class AppController extends Controller
{
public function initialize()
{
parent::initialize();
$this->loadComponent('RequestHandler');
$this->loadComponent('Flash');
$this->loadComponent('Cookie');
//set up initial cart cookie
$this->response = $this->response->withCookie(
(new Cookie('cart'))
->withPath('/')
->withValue(json_encode([]))
->withExpiry(new \DateTime('+1 month'))
);
}
I then have it set up in the CartController to add selected items to the cart cookie:
<?php
// src/Controller/CartController.php
namespace App\Controller;
use Cake\I18n\Time;
use Cake\Http\Cookie\Cookie;
use Cake\Http\Cookie\CookieCollection;
class CartController extends AppController
{
public function index()
{
$cart = json_decode($this->request->getCookie('cart'));
$add_cart = ($this->request->getQuery('add') == null ? [] : $this->request->getQuery('add'));
if (count($add_cart) > 0) {
foreach($add_cart as $ac) {
if(!in_array($ac, $cart)) {
$cart[] = $ac;
}
}
}
//replace cookie
$this->response = $this->response->withCookie(
(new Cookie('cart'))
->withPath('/')
->withValue(json_encode($cart))
->withExpiry(new \DateTime('+1 month'))
);
$this->loadModel('Books');
$cart_items = [];
foreach($cart as $cartp) { //'contain' => ['BookTypes'],
$book = $this->Books->get($cartp, ['fields' => array('id','name','description')]);
$cart_items[] = $book;
}
$this->set(compact('cart_items'));
}
If I stay within "Cart", the cookie keeps the value. However, as soon as I move to any other page (home page or browsing books), the cookie value is reset to empty (an empty array).
What is causing this?
I found my problem.
Had to move the initial cookie from the initialize() to beforeFilter() in AppController.php and now it seems to be working.

associated data in Mailer in CakePHP 3

I'm working on CakePHP 3.4
I have a contact_messages table to save message via form on website.
I want to send user an email whenever a new message is saved.
For that, I have created mailer class like
<?php
namespace App\Mailer;
use Cake\Mailer\Mailer;
use Cake\Event\Event;
use Cake\Datasource\EntityInterface;
class ContactMessageMailer extends Mailer
{
public function newMessage($message)
{
$this
->setProfile('no-reply')
->setTemplate('new_message')
->setLayout('message')
->setEmailFormat('html')
->setTo($user->email) // user email
->setSubject('Verify Account')
->setViewVars(['name' => $user->first_name, 'email' => $user->email, 'message' => $message->body]);
}
public function implementedEvents()
{
return [
'Model.afterSave' => 'alertMessage'
];
}
public function alertMessage(Event $event, EntityInterface $entity, \ArrayObject $options)
{
if ($entity->isNew()) {
$this->send('newMessage', [$entity]);
}
}
}
and registering event in ContactMessagesTable.php
$mailer = new UserMailer(); //use App\Mailer\UserMailer;
$this->eventManager()->on($mailer);
ContactMessages belongsTo Users and Users is having email of user whom to send the email.
How can I get users information in Mailer?
Will probably do this;
In the User table;
public function processUser($user)
{
if($this->save($user)){
$event = new Event('Model.afterSave', $this, [$entity = $user])
$this->eventManager()->dispatch($event);
return true;
}else{
return false;
}
}
In ContactMessage Table ;
public function initialize()
{
parent::intialize();
$mailer = new UserMailer(); //use App\Mailer\UserMailer;
$this->Users->eventManager()->on($mailer); //ContactMessage has to be related to User table
}
Hope I was able to communicate.

Cant authentificate user with FOSUser bundle

I am creating an Angularjs app with Symfony 2.8 on the backend, using FOSUser bundle for the user management.
I have a controller to check the user login and create the user session, but when i try to create the user session symfony returns me this error message:
Controller "UserBundle\Controller\LoginController::indexAction()" requires that you provide a value for the "$session" argument (because there is no default value or because there is a non optional argument after this one).
There is my controller code:
<?php
namespace UserBundle\Controller;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Session\Session;
use UserBundle\Entity\User;
class LoginController extends Controller
{
public function indexAction(Session $session)
{
$arrResult = array('STATUS' => 'ERROR', 'ERROR' => 'INIT', 'DATA' => array() );
// get post data
$postData = file_get_contents("php://input");
$postData = json_decode($postData, TRUE);
$email = $postData['email'];
$password = $postData['password'];
if( empty($email) || empty($password) )
{
$arrResult['ERROR'] = 'ALL_FIELDS_ARE_REQUIRED';
return new JsonResponse($arrResult);
}
$user_manager = $this->get('fos_user.user_manager');
$factory = $this->get('security.encoder_factory');
$user = $user_manager->findUserByEmail($email);
$encoder = $factory->getEncoder($user);
$salt = $user->getSalt();
if( $encoder->isPasswordValid($user->getPassword(), $password, $salt) )
{
// create user session
$this->createLoginSession($session, $user);
$arrResult['DATA'] = array('USERNAME' => $user->getUsername());
$arrResult['STATUS'] = 'OK';
}
else
{
$arrResult['ERROR'] = 'INVALID_CREDENTIALS';
}
return new JsonResponse($arrResult);
}
private function createLoginSession($session, $objUser)
{
$objToken = new UsernamePasswordToken($objUser, null, 'main', $objUser->getRoles() );
// save token
$objTokenStorage = $this->get("security.token_storage")->setToken($objToken);
$session->set( '_security_main', serialize($objToken) );
}
}
What i am doing wrong?
Thanks!

Symfony 2 how to call the renderView method in FormHandler?

I try to do a contact form with Symfony 2.4.1. My form is a simple contact one without an entity.
The following error happens in my handler :
FatalErrorException: Error: Call to undefined method Symfony\Component\Form\Form::render() in C:\Program Files\wamp\www\sf2\src\Open\OpcBundle\Form\Handler\ContactHandler.php line 75
And the form handler code :
<?php
// src/Open/OpcBundle/Form/Handler/Handler.php
namespace Open\OpcBundle\Form\Handler;
use Symfony\Component\Form\Form;
use Symfony\Component\HttpFoundation\Request;
class ContactHandler {
protected $request;
protected $form;
protected $mailer;
public function __construct(Form $form, Request $request, $mailer) {
$this->form = $form;
$this->request = $request;
$this->mailer = $mailer;
}
public function process() {
if ('POST' == $this->request->getMethod()) {
$this->form->handleRequest($this->request);
$data = $this->form->getData();
$this->onSuccess($data);
return true;
}
return false;
}
protected function onSuccess($data) {
$message = \Swift_Message::newInstance()
->setContentType('text/html')
->setSubject($data['sujet'])
->setFrom($data['courriel'])
->setTo('me#gmail.com')
->setBody($this->render('OpcOpenBundle:Opc:Mails/contact.html.twig',
array('ip' => $request->getClientIp(),
'nom' => $data['nom'],
'msg' => $data['msg'])
)
);
$this->get('mailer')->send($message);
$request->getSession()->getFlash()->add('success', 'Your email has been sent! Thanks!');
return $this->redirect($this->generateUrl('contact'));
}
}
So the problem is that I don't have an object/instance for the renderView() method to call the template mail with setBody in the function onSuccess()
Which object/instance should I use for ?
Thanks
PS: sorry for my english, i'm French!
It's Symfony\Bundle\TwigBundle\TwigEngine class. service name is 'templating'.
BTW, why is you handler is not service?

Using session component in custom component

I'm trying to use Session component in custom component (CakePHP 2.3) but when I call Session component functions I get: Fatal error: Call to a member function read() on a non-object in ...\app\Controller\Component\CartComponent.php on line 7
My CartComponent looks like that:
<?php
App::uses('Component', 'Controller');
class CartComponent extends Component {
public $components = array('Session');
function hasItems() {
$cart = $this->Session->read('Cart');
return $cart != null && count($cart) > 0;
}
}
?>
And I use it in controller:
<?php
class OrdersController extends AppController {
public $name = 'Orders';
public $components = array('Cart', 'Email');
function beforeFilter() {
parent::beforeFilter();
if ($this->Cart->hasItems()) {
$this->Auth->allow('add_item', 'remove_item', 'cart');
} else {
$this->Auth->allow('add_item', 'remove_item', 'cart', 'make');
}
}
}
?>
For using session inside the custom component I tried with
public $components = array('Session');
and then called it by using
$this->Session->read('Cart');
but I cant able to use it and I start to use
CakeSession::read('Cart')
Now it works Hope it will used for you note I used in cake php version > 2
If you want to use Session in your Component Use-
$test = CakeSession::read('user');
print_r($test);
You should use as bellow
class YourComponent extends Component {
public function initialize(Controller $controller){
$this->controller = $controller;
if (!isset($this->controller->presetVars)) {
$this->controller->presetVars = true;
}
$model = $this->controller->modelClass;
if (!empty($settings['model'])) {
$model = $settings['model'];
}
if ($this->controller->presetVars === true) {
// auto-set the presetVars based on search definitions in model
$this->controller->presetVars = array();
$filterArgs = array();
if (!empty($this->controller->$model->filterArgs)) {
$filterArgs = $this->controller->$model->filterArgs;
}
foreach ($filterArgs as $key => $arg) {
if ($args = $this->_parseFromModel($arg, $key)) {
$this->controller->presetVars[] = $args;
}
}
}
foreach ($this->controller->presetVars as $key => $field) {
if ($field === true) {
if (isset($this->controller->$model->filterArgs[$key])) {
$field = $this->_parseFromModel($this->controller->$model->filterArgs[$key], $key);
} else {
$field = array('type' => 'value');
}
}
if (!isset($field['field'])) {
$field['field'] = $key;
}
$this->controller->presetVars[$key] = $field;
}
/* now you can use Component existing in your Component :) */
public function sayHello(){
$this->controller->Session->setFlash(__('Hello you'));
}
}

Resources