Topic-icon Redirect JFBC User Registrations to akeeba subscriptions

Active Subscriptions:

None
12 years 10 months ago - 12 years 10 months ago #34630 by learnthrusong
Hi Alex,

This post is a consolidation of the topic I mistakenly created in JLinked Board which you can now delete if you wish. The topic in question: www.sourcecoast.com/forums/jlinked/jlink...akeeba-subscriptions

Background
I'm building a site for a client where all new users are registered through Akeeba Subscriptions. Without JFBConnect installed, the akeeba subs redirect user registrations plugin handles the redirection fine however, with JFBC installed, clicking the login with facebook button always redirects users to index.php?option=com_jfbconnect&view=loginregister&return=XXXXXXXXXXXXXXXX

Goal
I'm trying to achieve the same kind of registration flow as you guys use for your subscriptions, with one difference: ideally all new user accounts will be created in Akeeba subs, i.e. never will the user be able to access the standard joomla or jfbc (loginregister) registration page. So, to clarify,
  1. the user chooses a subscription package from either the com_akeeba&view=levels view or directly at the subs page, i.e. com_akeeba&view=level&slug=mysubpackage
  2. upon viewing the subscription page (com_akeeba&view=level&slug=mysubpackage):
    - logged in users should see the subscription form
    - logged in users should see the login form + fb login button above the subscription form
Questions
  1. So, my question is, how can I override this so that I always redirect the user to register in com_akeebasubs instead? I think that I need to override the loginFacebookUser() method to do this, right?
  2. I notice that you aren't using the return var in the URL. Are you passing this in the post?
  3. FYI, as part of the job for my client, I've also developed a number of additional plugins including a system plugin and akeeba subs plugin. If I'm correct in my assumption, I can override this redirection (loginFacebookUser()) in my system plugin, right?
  4. Naturally, I don't want to hack your core controller's loginFacebookUser() method - or any other for that matter. Also, are there any other methods I will need to override?

Further information (Relating to Q3/4)
BTW, I've updated my post on how to integrate the facebook data from JFBC into the subscription form . It isn't exactly how I'm doing it as I'm having to do a lot of data manipulation/conversion with dates (D.O.B. field for instance) and also to auto select the country/state in the akeeba dropdowns etc but, this is essentially enough to get someone most of the way there now think. Is that all looking ok to you?

In my earlier post in that topic ( p34095 ), I document how I was originally planning to inject the FB user data by overriding the level controller in a system plugin. As you can see from my later post, this wasn't possible because of how akeeba subs cache is set - hence my last post in that topic. However, I hope to be able to override JFBC's controller's/Model's methods in this way - should I need to of course!

Anyway, I'd really appreciate some advice on how to achieve this.

Many thanks once again to you for this wonderful extension!!! ;)

Many thanks,

Gez
Last edit: 12 years 10 months ago by learnthrusong.
The topic has been locked.
Support Specialist
Hmmm... JFBConnect won't work how you want it to like that. We need to register the user because that's where we make the connection between the user's Facebook ID and their Joomla ID.

I'm a little confused as to what you're goal is. Do you want the user to use the Akeeba Subscriptions form because there's some information you want them to add? If so, can't that data be imported or entered later during the subscription process?

Ultimately, I believe you could probably use 'our' login button and then redirect to the Akeeba Subscriptions registration page, but you'd need to do a lot of the validation checks that JFBConnect does normally during the registration process, get the proper authentication token, 'map' the connection between Joomla/Facebook, and more. It's not just a simple process of changing the redirection.

I guess if you can explain more about why you 'need' the Akeeba registration form, instead of automatically creating the user with JFBConnect and then letting them edit that info during the subscription process. We do that process on this site where the user can login/register with FB on the subscriptions page, and then we hide/show specific fields that they may want to modify after the registration.

If you really need to do what you're looking for, the change to JFBConnect would be minor.. basically, you'd modify our Javascript file and change the redirect from loginFacebookUser to wherever you want. Then, you'd have to re-implement all the code above, which could be tedious.

Finally, I'm not sure what you mean by:

I notice that you aren't using the return var in the URL. Are you passing this in the post?

Can you explain that a bit more?

Keep me posted on the above, and we'll help how we can.

Thanks,
Alex
The topic has been locked.
Active Subscriptions:

None
12 years 10 months ago - 12 years 10 months ago #34658 by learnthrusong
Hi Alex,

Thanks for your reply!

alzander wrote: Hmmm... JFBConnect won't work how you want it to like that. We need to register the user because that's where we make the connection between the user's Facebook ID and their Joomla ID.

Since Akeeba Subscriptions creates the joomla user when user registration redirect to akeebasubs plugin is used, can we not just get that from akeeba subs instead?

alzander wrote: I'm a little confused as to what you're goal is. Do you want the user to use the Akeeba Subscriptions form because there's some information you want them to add? If so, can't that data be imported or entered later during the subscription process?

&&

alzander wrote: I guess if you can explain more about why you 'need' the Akeeba registration form, instead of automatically creating the user with JFBConnect and then letting them edit that info during the subscription process. We do that process on this site where the user can login/register with FB on the subscriptions page, and then we hide/show specific fields that they may want to modify after the registration.Yes, I do have other data that I'm also capturing however, this is not really the reason why I want to redirect to akeeba subs. The reason.I want to do this is because I really want to make the whole registration process no longer than 3 steps. The subscription is an online course with custom 'timed' group upgrades on each package (akeebasubs level) and are the only possible membership types from the frontend

alzander wrote: Ultimately, I believe you could probably use 'our' login button and then redirect to the Akeeba Subscriptions registration page, but you'd need to do a lot of the validation checks that JFBConnect does normally during the registration process, get the proper authentication token, 'map' the connection between Joomla/Facebook, and more. It's not just a simple process of changing the redirection.

What would I need to do to achieve this?

alzander wrote: If you really need to do what you're looking for, the change to JFBConnect would be minor.. basically, you'd modify our Javascript file and change the redirect from loginFacebookUser to wherever you want.

Cool! Thanks for the tip!

alzander wrote: Then, you'd have to re-implement all the code above, which could be tedious

Please could you elaborate on this, in particular the, " ... all the code above, ..." part? Which code above?

RE: "Finally, I'm not sure what you mean by":

learnthrusong wrote: I notice that you aren't using the return var in the URL. Are you passing this in the post?

alzander wrote: Can you explain that a bit more?

Sure, I think I mistakenly presumed that when you go to the subs page on your site for a particular component, JFBC for instance, if you login in with facebook from that page, most of the fields hide and there is no 'return' parameter in the url whereas, jfbcs loginregister view contains a return parameter.


Please let me know if you need any further info. Thanks again!!!

Gez!
Last edit: 12 years 10 months ago by learnthrusong.
The topic has been locked.
Support Specialist

Since Akeeba Subscriptions creates the joomla user when user registration redirect to akeebasubs plugin is used, can we not just get that from akeeba subs instead?

You'd be able to get the Joomla User ID, but you'd have to add code to check if the user previously logged in through Facebook and, if so, get the Facebook User Id and store the connection between the 2 IDs in the database.

The reason.I want to do this is because I really want to make the whole registration process no longer than 3 steps.

* User clicks "Login with Facebook" - Joomla account is automatically created and user is redirected to the Akeeba Subscriptions page
* Akeeba Subs can ask for any additional information.
This assumes the "Registration Mode" setting in JFBConnect is "Automatic"
That seems like less than 3 steps, but again, maybe I'm missing something.

What would I need to do to achieve this?

If you are not using the loginFacebookUser function, then JFBConnect won't be storing the user's Facebook ID and Joomla ID in the database to make the connection ('user map'). If that's not done, when the user returns to the site later on and clicks the Login with Facebook button, JFBConnect won't know what Joomla user to login.

All the code above

All the code is the what's mentioned above with the mapping of the users. Basically, all the code you'll be skipping in the loginFacebookUser block.

Hope that helps explain some more. I'm still a bit lost as to why the Automatic Registration process doesn't help you get closer to where you want to be.

Thanks,
Alex
The topic has been locked.
Active Subscriptions:

None
Hi Alex,

alzander wrote: You'd be able to get the Joomla User ID, but you'd have to add code to check if the user previously logged in through Facebook and, if so, get the Facebook User Id and store the connection between the 2 IDs in the database.

Sure, I understand...

alzander wrote: * User clicks "Login with Facebook" - Joomla account is automatically created and user is redirected to the Akeeba Subscriptions page
* Akeeba Subs can ask for any additional information.
This assumes the "Registration Mode" setting in JFBConnect is "Automatic"
That seems like less than 3 steps, but again, maybe I'm missing something.

I'll give 'Automatic Registration a go... I've never used this in JFBC because, well, I can't remember why but I'm sure there was a reason... I'll look into this and feedback...

What would I need to do to achieve this?

If you are not using the loginFacebookUser function, then JFBConnect won't be storing the user's Facebook ID and Joomla ID in the database to make the connection ('user map'). If that's not done, when the user returns to the site later on and clicks the Login with Facebook button, JFBConnect won't know what Joomla user to login.

alzander wrote: All the code above All the code is the what's mentioned above with the mapping of the users. Basically, all the code you'll be skipping in the loginFacebookUser block. Hope that helps explain some more. I'm still a bit lost as to why the Automatic Registration process doesn't help you get closer to where you want to be.

Thanks for the clarification!

Just a quick question as I'm not really sure about the behaviour since I haven't tried automatic registration... Presumably, if someone is on the subs page, say a specific level (slug=sub1) and they click login with Facebook, the 'standard' fields requested in the JFBC config will be registered and then the user is auto redirected to the same page they were on via the return=XXXXXXXXXXXXXXXXXXXXX parameter, right?

Thanks again for the clarification and this wonderful component!!!

Gez
The topic has been locked.
Support Specialist
Gez,
I think Automatic will help things out a bit. As for the redirection, the return parameter is used to return the user to the same page *if* the "Enable New User Redirection" setting in JFBConnect is set to "No". If it's set to Yes, then that will force the user to the specified menu item in those settings.

I hope that helps,
Alex
The topic has been locked.
Active Subscriptions:

None
Great, thanks Alex!

I'll check it out first thing in the morning and post my findings. I wish I'd realised about the automatic setting!!!

Many thanks!

Gez
The topic has been locked.
Support Specialist
Sounds great. Can't wait to hear how that goes for you.

Thanks,
Alex
The topic has been locked.
Active Subscriptions:

None
Hi Alex,

Well it seems that Auto Crete Users is the answer! ;) Thanks for that!

So, now I'm trying to work out how I can effectively hide the fields according to the setting that I've configured in my Social Plugin for Akeeba Subscriptions. I see that there are methods for this however, I'm a little unsure how to proceed...

So to clarify, what I've done is followed the Kunena profile plugin, overridden the getProfileFields() method and built the configuration page for the admin side. All of the fields that I require here are set in the array that's returned from the getProfileFields() method but what other methods do I need to override in my social profile to manage this?

many thanks,

Gez

PS Do I actually need the protected function createUser($profileData) & protected function saveProfileField($fieldId, $value) methods since akeeba subs is going to handle saving this once I've injected the FB data into the form?
The topic has been locked.
Active Subscriptions:

None
Hi Alex,

Further to my last post, I believe that I will need to use the protected function createUser($profileData) & protected function saveProfileField($fieldId, $value) methods, right?

Just in case, I've updated those methods in my plugin class and added a couple of other methods that I'd previously used in my system plugin to transform the country, state & gender strings from facebook. Ultimately, these will allow me to populate the akeeba subs form, correctly selecting the gender, state and country select lists.

For note, I do this by:
1. including the Akeebasubs component helper in the plugin
2. Getting the states and countries arrays (properties) from the helper
3. Initialising states and countries properties in my SocialProfile to lookup later

So, now my createUser & saveProfileField methods look like:
protected function createUser($profileData)
{
    $query = "INSERT IGNORE INTO #__akeebasubs_users (userid) VALUES (" . $this->db->quote($this->joomlaId) . ")";
    $this->db->setQuery($query);
    $this->db->execute();
    
    // Custom fields stored as params
    $akCustomFieldKeys = array("agreetotos", "dob", "phone", "mobile","gender");
    $akCustomFields = '';

    // 
    foreach ($this->getProfileFields() as $name => $displayName){
        // Regular fields
        if(!in_array($name, $akCustomFieldKeys)){
            if($name == "state"){ // We need to pass the country too
                $this->saveProfileField($name, array($profileData->getFieldWithUserState($name), $profileData->getFieldWithUserState("country")));
            }else{
               $this->saveProfileField($name, $profileData->getFieldWithUserState($name)); 
            }
            
        }else{ // custom (params) fields
            // concatenate string of values
            $akCustomFields .= '"' . $name . '":"' . $profileData->getFieldWithUserState($name) . '"';
        }
    }
    
    // Check if any custom (params) fields included
    if(is_string($akCustomFields) && strlen($akCustomFields) > 5){
        $akCustomFields = '{' . $akCustomFields . '}';
        // Save the field
        $this->saveProfileField('params', $akCustomFields);
    }
}

protected function saveProfileField($fieldId, $value)
{
    $addStateToAddress2 = false; // flag - used to determine if state should be appended to address2 field

    // Load the language file for gender used below
    $lang = JFactory::getLanguage();
    $lang->load('com_jfbconnect');

    switch ($fieldId)
    {
        case "dob":
            //$value = date('m/d/Y',strtotime($value)); // - This is the original from system plugin
            $value = new JDate($value);
            $value = $value->toSql();
            break;
            
        case "gender":
            $value = $this->getGenderIdFromString($value);
            break;
            
        case "state":
            $originalValue = $value[0]; // The state
            $value = $this->getLocationIdFromName('states', $value[0], $value[1]); // $value[1] is the country
            if(trim($value[0]) == ""){
                $addStateToAddress2 = true;
                $state = $originalValue;
            }
            break;
        
        case "country":
            $value = $this->getLocationIdFromName('countries', $value);
            break;
            
    }
    
    $this->db->setQuery("UPDATE #__akeebasubs_users SET `" . $fieldId . "` = " . $this->db->quote($value) . " WHERE userid=" . $this->joomlaId);
    $this->db->execute();
    
    // If a state was present from FB but doesn't exist in the Akeeba States 
    if($addStateToAddress2){
        // Check that the state isn't already part of address2
        $this->db->setQuery("SELECT address2 FROM #__akeebasubs_users WHERE userid =" . $this->joomlaId);
        $result = $this->db->execute();
        
        // If the state isn't found in address2 field
        if(!strpos($state, $result)){
            //append it to the value
            $this->db->setQuery("UPDATE #__akeebasubs_users SET address2 = CONCAT(address2, ', " . $state . "') WHERE userid=" . $this->joomlaId);
            $this->db->execute();
        }
    } 
}
And, the following methods that that transform the FB string data to populate select boxes in Akeeba subs:
/**
 * Method to get the Country/State ID from name of the state/country
 * 
 * @param   string  $type       The type to get - 'countries' or 'states'
 * @param   string  $name       The name of the country/state
 * @param   string  $country    The name of country - ONLY used in case of state lookup
 * @return  sting   $returnID   Either 2 letter ISO Country/State code or nothing if not found
 */
public function getLocationIdFromName($type, $name, $country="")
{
    // Valid types to check against
    $types = array('countries', 'states');
    
    // To return
    $returnID = ""; // Default
    
    // Check we have values to search on
    if((!is_string($name) || strlen($name) <= 0) || 
        (!in_array($type, $types) || !is_string($type)))
        return $returnID;
    
    switch($type){
        case "countries":
            if(is_array($this->countries) && count($this->countries) > 0)
                $returnID = (string)array_search($name, $this->$type);
            break;
            
        case "states":
            // Bail out if no country is passed or if no states present for the country
            if(is_string($country) && strlen($country) > 1 && array_key_exists($country, $this->$type)){
                $states = $this->$type;
                $returnID = (string)array_search($name, $states[$country]);
            }
            break;
            
        default:
            break;
    }
    
    // return
    return $returnID;
}

/**
 * Method to get the gender ID from string
 * Transforms the 'male'/'female' strings from facebook
 * to populate the subscription form with relevant numeric ID
 * 
 * @param   string  $string     "male" or "female" - anything else returns 0
 * @return  int     $genderID   0 = not specified, 1 = male, 2 = female
 */
public function getGenderIdFromString($string)
{
    $genderID = 0; //Default
    
    // Check there was a string passed in
    if(!is_string($string) || strlen($string) <= 1)
        return $genderID; // return the default
    
    switch($string){
        case "male":
            $genderID = 1;
            break;
        case "female":
            $genderID = 2;
            break;
        default:
            $genderID = 0;
            break;
        
    }
    // return ID
    return $genderID;
}
Questions
What do I need to update in the following method to ensure that the fields are displayed/not displayed according to my Akeebasubs social plugin?
/**
* Get field names and inputs to request additional information from users on registration
* @return string HTML of form fields to display to user on registration
*/
public function socialProfilesOnShowRegisterForm($network)
{
    $this->loadSettings($network);
    $profileData = $this->fetchProfileFromFieldMap(false);
    $html = $this->getRegistrationForm($profileData);
    return $html;
}
Do I also need to override the protected function getRegistrationForm($profileData) method in my plugin to achieve this?

Thanks again!!!

Gez
The topic has been locked.