<?php
/**
 * HybridAuth
 * http://hybridauth.sourceforge.net | http://github.com/hybridauth/hybridauth
 * (c) 2009-2014, HybridAuth authors | http://hybridauth.sourceforge.net/licenses.html
 */

/**
 * To implement an OpenID based service provider, Hybrid_Provider_Model_OpenID
 * can be used to save the hassle of the authentication flow.
 *
 * Each class that inherit from Hybrid_Provider_Model_OAuth2 have only to define
 * the provider identifier : <code>public $openidIdentifier = ""; </code>
 *
 * Hybrid_Provider_Model_OpenID use LightOpenID lib which can be found on
 * Hybrid/thirdparty/OpenID/LightOpenID.php
 */
class Hybrid_Provider_Model_OpenID extends Hybrid_Provider_Model
{

    /**
     * Openid provider identifier
     *
     * @var string
     */
    public $openidIdentifier = '';

    // --------------------------------------------------------------------


    /**
     * adapter initializer
     */
    function initialize()
    {
        if (isset($this->params['openid_identifier'])) {
            $this->openidIdentifier = $this->params['openid_identifier'];
        }

        // include LightOpenID lib
        include_once Hybrid_Auth::$config['path_libraries'].'OpenID/LightOpenID.php';

        // An error was occurring when proxy wasn't set. Not sure where proxy was meant to be set/initialized.
        Hybrid_Auth::$config['proxy'] = isset(Hybrid_Auth::$config['proxy']) ? Hybrid_Auth::$config['proxy'] : '';

        $hostPort = parse_url(Hybrid_Auth::$config['base_url'], PHP_URL_PORT);
        $hostUrl  = parse_url(Hybrid_Auth::$config['base_url'], PHP_URL_HOST);

        // Check for port on url
        if ($hostPort) {
            $hostUrl .= ':'.$hostPort;
        }

        $this->api = new LightOpenID($hostUrl, Hybrid_Auth::$config['proxy']);

    }//end initialize()


    // --------------------------------------------------------------------


    /**
     * begin login step
     */
    function loginBegin()
    {
        if (empty($this->openidIdentifier)) {
            throw new Exception("OpenID adapter require the identity provider identifier 'openid_identifier' as an extra parameter.", 4);
        }

        $this->api->identity  = $this->openidIdentifier;
        $this->api->returnUrl = $this->endpoint;
        $this->api->required  = [
            'namePerson/first',
            'namePerson/last',
            'namePerson/friendly',
            'namePerson',

            'contact/email',

            'birthDate',
            'birthDate/birthDay',
            'birthDate/birthMonth',
            'birthDate/birthYear',

            'person/gender',
            'pref/language',

            'contact/postalCode/home',
            'contact/city/home',
            'contact/country/home',

            'media/image/default',
        ];

        // redirect the user to the provider authentication url
        Hybrid_Auth::redirect($this->api->authUrl());

    }//end loginBegin()


    // --------------------------------------------------------------------


    /**
     * finish login step
     */
    function loginFinish()
    {
        // if user don't grant access of their data to your site, halt with an Exception
        if ($this->api->mode == 'cancel') {
            throw new Exception('Authentication failed! User has canceled authentication!', 5);
        }

        // if something goes wrong
        if (! $this->api->validate()) {
            throw new Exception('Authentication failed. Invalid request received!', 5);
        }

        // fetch received user data
        $response = $this->api->getAttributes();

        // store the user profile
        $this->user->profile->identifier = $this->api->identity;

        $this->user->profile->firstName   = ( array_key_exists('namePerson/first', $response) ) ? $response['namePerson/first'] : '';
        $this->user->profile->lastName    = ( array_key_exists('namePerson/last', $response) ) ? $response['namePerson/last'] : '';
        $this->user->profile->displayName = ( array_key_exists('namePerson', $response) ) ? $response['namePerson'] : '';
        $this->user->profile->email       = ( array_key_exists('contact/email', $response) ) ? $response['contact/email'] : '';
        $this->user->profile->language    = ( array_key_exists('pref/language', $response) ) ? $response['pref/language'] : '';
        $this->user->profile->country     = ( array_key_exists('contact/country/home', $response) ) ? $response['contact/country/home'] : '';
        $this->user->profile->zip         = ( array_key_exists('contact/postalCode/home', $response) ) ? $response['contact/postalCode/home'] : '';
        $this->user->profile->gender      = ( array_key_exists('person/gender', $response) ) ? $response['person/gender'] : '';
        $this->user->profile->photoURL    = ( array_key_exists('media/image/default', $response) ) ? $response['media/image/default'] : '';

        $this->user->profile->birthDay   = ( array_key_exists('birthDate/birthDay', $response) ) ? $response['birthDate/birthDay'] : '';
        $this->user->profile->birthMonth = ( array_key_exists('birthDate/birthMonth', $response) ) ? $response['birthDate/birthMonth'] : '';
        $this->user->profile->birthYear  = ( array_key_exists('birthDate/birthDate', $response) ) ? $response['birthDate/birthDate'] : '';

        if (isset($response['namePerson/friendly']) && ! empty($response['namePerson/friendly']) && ! $this->user->profile->displayName) {
            $this->user->profile->displayName = $response['namePerson/friendly'];
        }

        if (isset($response['birthDate']) && ! empty($response['birthDate']) && ! $this->user->profile->birthDay) {
            list( $birthday_year, $birthday_month, $birthday_day ) = $response['birthDate'];

            $this->user->profile->birthDay   = (int) $birthday_day;
            $this->user->profile->birthMonth = (int) $birthday_month;
            $this->user->profile->birthYear  = (int) $birthday_year;
        }

        if (! $this->user->profile->displayName) {
            $this->user->profile->displayName = trim($this->user->profile->firstName.' '.$this->user->profile->lastName);
        }

        if ($this->user->profile->gender == 'f') {
            $this->user->profile->gender = 'female';
        }

        if ($this->user->profile->gender == 'm') {
            $this->user->profile->gender = 'male';
        }

        // set user as logged in
        $this->setUserConnected();

        // with openid providers we get the user profile only once, so store it
        Hybrid_Auth::storage()->set("hauth_session.{$this->providerId}.user", $this->user);

    }//end loginFinish()


    // --------------------------------------------------------------------


    /**
     * load the user profile from the IDp api client
     */
    function getUserProfile()
    {
         // try to get the user profile from stored data
        $this->user = Hybrid_Auth::storage()->get("hauth_session.{$this->providerId}.user");

        // if not found
        if (! is_object($this->user)) {
            throw new Exception("User profile request failed! User is not connected to {$this->providerId} or his session has expired.", 6);
        }

        return $this->user->profile;

    }//end getUserProfile()


}//end class
