when i create a user with facebook-sdk, i don't get him logged in automaticaly after facebook-login.
Usercreation working well, but no login.
Cakephp and facebook-sdk are latest versions.
here is my accountController:
<?php
class AccountController extends AppController {
public $uses = array('User');
public function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow('login');
#$this->Auth->authenticate = array('Basic' => array('fields' =>array('username' => 'fb_id', 'password' => 'random')));
}
public function login() {
$this->facebook = new Facebook(array(
'appId' => '14549077xxxx',
'secret' => '95a38f3xxxx',
'cookie' => 'true'
));
$user = $this->facebook->getUser();
if($user){
try{
$params = array('next' => 'http://'.$_SERVER['HTTP_HOST'].'/account/logout');
$this->Session->write('logoutLink', $this->facebook->getLogoutUrl($params));
#if (!$this->Auth->user()) {
$fb_user = $this->facebook->api('/me');
$authUser = $this->User->findByFbId($user);
if (empty($authUser)) {
$pw = $this->__randomString();
$authUser = array(
'fb_id' => $user,
'random' => $pw,
'password' => $this->Auth->password($pw),
'email' => $fb_user['email']
);
$this->User->create();
$this->User->save($authUser);
$authUser = $this->User->findByFbId($user);
}
$this->Auth->authenticate = array(
'Form' => array(
'fields' => array('username' => 'fb_id', 'password' => 'random')
)
);
$this->Auth->login($authUser['User']);
$this->redirect($this->Auth->redirect());
#}
}catch(FacebookApiException $e){
$user = NULL;
}
}
if(empty($user)){
$loginurl = $this->facebook->getLoginUrl(array(
'scope'=> 'email,publish_stream,read_friendlists',
'redirect_uri' => 'http://'.$_SERVER['HTTP_HOST'].'/account/login',
));
$this->redirect($loginurl);
}
}
public function dashboard() {
echo 'logged in';
}
}
Users will always get redirect to login page.
$authUser is always filled correctly.
Pls Help :)
Greetings
m.
my AppController
class AppController extends Controller {
public $components = array('Auth','Session');
public function beforeFilter() {
$this->Auth->loginRedirect = array('controller' => 'account', 'action' => 'dashboard');
$this->Auth->logoutRedirect = '/';
$this->Auth->loginAction = array('controller' => 'pages', 'action' => 'login');
}
Sessions:
Configure::write('Session', array(
'defaults' => 'php'
));
problem solved in chat:
Facebook is creating a new session,
$this->facebook = new Facebook(array(
'appId' => '14549077xxxx',
'secret' => '95a38f3xxxx',
'cookie' => 'true'
));
this code has to written down in appcontroller
public function beforeFilter() {
$this->Auth->loginRedirect = array('controller' => 'account', 'action' => 'dashboard');
$this->Auth->logoutRedirect = '/';
$this->Auth->loginAction = array('controller' => 'pages', 'action' => 'login');
$this->facebook = new Facebook(array(
'appId' => '14549077xxx',
'secret' => '95a38f3xxx',
'cookie' => 'true'
));
}
Thank you so much #noslone for trying together :D
Providing data $this->Auth->login($authUser['User']); to log a user in is wrong.
As per CakePHP documentation:
In 2.0 $this->Auth->login($this->request->data) will log the user in with whatever data is posted, whereas in 1.3 $this->Auth->login($this->data) would try to identify the user first and only log in when successful.
You should do something like this:
$this->request->data['User'] = $authUser['User'];
$this->request->data['User']['password'] = $authUser['User']['random'];
$this->Auth->login();
I have also added $this->request->data['User']['password'] = $authUser['User']['random']; because i think it fails to authenticate when providing the encrypted password to login.
If you have any other trouble, I am developing a Plugin that uses Facebook oAuth as an authentication object for Auth Component. If you want an already-built solution that uses server-side Facebook login, please check my website: http://marianofino.github.com/Facebook-Plugin-for-CakePHP/
Related
I'm trying to save my ManyToMany relations between users and categories. Actually I'm trying to save my category with given users, but this doesn't work.
Form
$builder->add('name')
->add('users', EntityType::class, array(
'label' => 'Benutzer',
'class' => 'AppBundle\Entity\User',
'multiple' => true,
'expanded' => true,
'required' => false,
'choice_label' => function (User $user) {
return $user->getUsername();
}
))
->add('submit', SubmitType::class, array(
'label' => 'Speichern'
));
Form Handler
public function onSuccess(Request $request)
{
// Get category from form
$category = $this->getForm()->getData();
// Redirect to parent category when setted
if ($this->parent) {
$category->setParent($this->parent);
$response = new RedirectResponse($this->router->generate('categories.view', [
'category' => $this->parent->getId()
]));
} else {
// Build new redirect response
$response = new RedirectResponse($this->router->generate('categories.view', [
'category' => $category->getId()
]));
}
try {
// Save category in database
$this->em->merge($category);
$this->em->flush();
} catch (ORMException $ex) {
throw $ex;
}
return $response;
}
Maybe you have to unserialize the Entity $category first?
$detachedCategory = unserialize($category);
$this->em->merge($detachedCategory);
$this->em->flush();
I found this link regarding that:
How to manage deserialized entities with entity manager?
Not sure if that's the answer, but you might want to do more research.
I'm using a form on add and edit page in which there is a input file which is required for add record but it is not required on edit page. Is there a way to change attribute on different pages?
$builder->add('title', 'text', array(
'required' => true,
))->add('description', 'textarea', array(
'required' => false,
))->add('fileName', 'file', array(
'data_class' => null,
'required' => true,
'label' => 'Upload File'
));
this is my controller
if ($custFile === null) {
$custFile = new File();
}
$fileForm = $this->createForm(new CustomerFileType(), $custFile);
$fileForm->handleRequest($request);
if ($fileForm->isValid()) {
$data = $fileForm->getData();
$custFile->setUserType('customer');
$custFile->setUserId($request->get('id'));
$custFile->setDateAttached($data->date);
$om->persist($data);
$file = $custFile->getFileName();
if ($file instanceof UploadedFile) {
$uploadManager = $this->get('probus_upload.upload_manager.user_files');
if ($newFileName = $uploadManager->move($file)) {
$custFile->setFileName(basename($newFileName));
}
}
$om->flush();
return $this->redirect($this->generateUrl('minicasp_customer_edit_customer', array(
'id' => $request->get('id'),
)));
}
$fileRecord = array();
if (null !== $customer) {
$fileRecord = $om->createQueryBuilder()
->from('MinicaspCustomerBundle:file', 'f')
->select('f')
->where('f.userId = :customer')
->andWhere('f.userType = :userType')
->orderBy('f.id', 'DESC')
->setParameter('customer', $request->get('id'))
->setParameter('userType', 'customer')
->getQuery()
->getResult()
;
}
return $this->render('MinicaspCustomerBundle:Default:customerAccount.html.twig', array(
'form' => $form->createView(),
'payment_form' => $paymentForm->createView(),
'file_form' => $fileForm->createView(),
'payments' => $payments,
'file_record' => $fileRecord,
'file_edit' => $fileEdit
));
Get your object inside form class and check if your add or edit new record, and based by this set the value of "required" attribute:
$obj = $builder->getData();
$builder->add('fileName', 'file', array(
'data_class' => null,
'required' => $obj->getId() === null ? true : false,
'label' => 'Upload File'
));
#Umair Malik, according to your last comment, you can try this in your controller:
if ($request->getMethod() == 'POST') {
$form->submit($request);
$formData = $form->getData();
if ($formData->getFile() !== null){
/*
* New file has been uploaded
* Save or copy your old record; after this will be over-written
*/
}
$entityManager->persist($formData);
$entityManager->flush();
}
You can create two form types, with different options.
On a side note, you don't need to put "required => true" that's the default option,
I was wondering if it's possible to send batched requests to maps.googleapis.com. As far as I can tell, it isn't.
I was using the Google API Client Library with supports batching, but it's only for www.googleapis.com. I went ahead and hacked it so that I could call the Places API, and it worked fine for normal calls, but when I actually tried to batch them, I got a 404 error:
"The requested URL /batch was not found on this server. That’s all we know."
So it appears that maps.googleapis.com does not support batching, but I wanted to be sure this is true. If anyone knows otherwise, please tell me how. Thanks!
inside google-api-php-client/src/Google/Config.php:
- 'base_path' => 'https://www.googleapis.com',
+ 'base_path' => 'https://maps.googleapis.com',
google-api-php-client/src/Google/Service/Maps.php:
(I added this file to make Places calls possible.)
<?php
class Google_Service_Maps extends Google_Service
{
const MAPS = "https://maps.googleapis.com/auth/maps";
public function __construct(Google_Client $client)
{
parent::__construct($client);
$this->servicePath = 'maps/api/';
$this->version = 'v3';
$this->serviceName = 'maps';
$this->places = new Google_Service_Maps_Places_Resource(
$this,
$this->serviceName,
'places',
array(
'methods' => array(
'autocomplete' => array(
'path' => 'place/autocomplete/json',
'httpMethod' => 'GET',
'parameters' => array(
'input' => array(
'location' => 'query',
'type' => 'string',
'required' => true,
),
'sensor' => array(
'location' => 'query',
'type' => 'boolean',
'required' => true,
),
'location' => array(
'location' => 'query',
'type' => 'string',
),
'radius' => array(
'location' => 'query',
'type' => 'integer',
),
),
),
)
)
);
}
}
class Google_Service_Maps_Places_Resource extends Google_Service_Resource
{
public function autocomplete($input, $lat, $lng, $radius, $optParams = array())
{
$params = array('input' => $input, 'location' => "$lat,$lng", 'radius' => $radius, 'sensor' => false);
$params = array_merge($params, $optParams);
return $this->call('autocomplete', array($params));
}
}
API batch calling code:
<?php
const API_KEY = 'MY_API_KEY';
set_include_path("google-api-php-client/src/" . PATH_SEPARATOR . get_include_path());
require_once 'Google/Client.php';
require_once 'Google/Service/Maps.php';
require_once 'Google/Http/Batch.php';
$client = new Google_Client();
$client->setApplicationName("Client_Library_Examples");
$client->setDeveloperKey(API_KEY);
$client->setUseBatch(true);
$batch = new Google_Http_Batch($client);
$service = new Google_Service_Maps($client);
$inputs = array(
'Dolore',
'MacAl',
'App Aca'
);
foreach($inputs as $input) {
$req = $service->places->autocomplete($input, 37.7833, -122.4167, 500);
$batch->add($req, $input);
}
$results = $batch->execute();
print_r($results);
print_r($req);
how can i validate the bill address depending on bill_ceck post parameter?
i reviewed the post validation (http://symfony.com/legacy/doc/cookbook/1_2/en/conditional-validator) but it seem to me like an AND validation not an OR.
class OrderAddForm extends BaseOprOrderHeaderForm {
public function configure() {
$this->setWidgets(array(
'email' => new sfWidgetFormInputText(),
'name' => new sfWidgetFormInputText(),
//....
'city' => new sfWidgetFormInputText(),
'street' => new sfWidgetFormInputText(),
//....
'bill_check' => new sfWidgetFormInputCheckbox(),
'bill_name' => new sfWidgetFormInputText(),
'bill_city' => new sfWidgetFormInputText(),
'bill_street' => new sfWidgetFormInputText(),
//....
));
$this->widgetSchema['bill_check']->setOption('value_attribute_value', 1);
$this->setValidators(array(
'email' => new sfValidatorEmail(),
'name' => new sfValidatorString(),
//...
'city' => new sfValidatorString(),
'street' => new sfValidatorString(),
//...
'bill_check' => new sfValidatorBoolean(),
));
if (/** the most convetional solution to check 'bill_check' state */) {
$this->validatorSchema['bill_name'] = new sfValidatorString();
$this->validatorSchema['bill_city'] = new sfValidatorString();
$this->validatorSchema['bill_street'] = new sfValidatorString();
//....
}
$this->widgetSchema->setNameFormat('orderAddForm[%s]');
}
}
thanks,
oliver
You could use a postValidator
public function configure() {
// your current code
$this->validatorSchema->setPostValidator(
new sfValidatorCallback(array('callback' => array($this, 'checkOtherStuff')))
);
}
public function checkOtherStuff($validator, $values)
{
// $values is an array of POSTed values
if ($values['bill_check'] == 'something in here')
{
if ($values['bill_city'] == '' || $values['bill_street'] == '') {
throw new sfValidatorError($validator, 'You must complete all fields');
}
}
// bill_check is correct, return the clean values
return $values;
}
Blog article on the subject here
I can't find a solution or right example for something that should be quite simple: assign a role to an user when creating it, this is what I'm trying:
$edit = array(
'name' => $_POST['name'],
'pass' => $password,
'mail' => $_POST['email'],
'status' => 0,
'language' => 'es',
'init' => $_POST['email'],
array(2 =>'authenticated', 4=>'my custom role') //as id and named in role db table
);
user_save(NULL, $edit);
The user is not being created, how can I do this?
Thank you
You haven't named the roles member as such. Try his modified version:
$edit = array(
'name' => $_POST['name'],
'pass' => $password,
'mail' => $_POST['email'],
'status' => 0,
'language' => 'es',
'init' => $_POST['email'],
'roles' => array(
2 => 'authenticated',
4 => 'my custom role',
),
);
user_save(NULL, $edit);
And you can use objects to do that.
// Check if user's email is unique
if (!user_load_by_mail($_POST['email'])) {
$account = new stdClass;
$account->name = $_POST['name'];
$account->pass = user_hash_password($password);
$account->mail = $_POST['email'];
$account->status = FALSE;
$account->language = 'es';
$account->init = $_POST['email'];
$account->roles = array(
DRUPAL_AUTHENTICATED_RID => TRUE,
'Your custom role' => TRUE,
);
user_save($account);
}
Here is a hook I've written to add a role to a user when a new user is inserted:
<?php
function MYMODULE_user_insert(&$edit, $account, $category){
if (array_key_exists('profile_1', $account)) {
$is_university = FALSE;
if ($account->profile_sport_club['field_club']['und'][0]['value'] == 1 ) {
$is_university = TRUE;
}
if ($is_university) {
$uid = $account->uid;
$role_name = 'uni_club';
if ($role = user_role_load_by_name($role_name)) {
user_multiple_role_edit(array($uid), 'add_role', $role->rid);
}
}
}
}
?>
Thanks to this tip, it's now much simpler.
function first_user_insert(&$edit, $account, $category, $node){
$uid = $account->uid;
$role_name = 'role name';
if ($role = user_role_load_by_name($role_name)) {
user_multiple_role_edit(array($uid), 'add_role', $role->rid);
}
}