<?php

/**
 * YiiSocialConnect.
 * Devuelve los datos de un usuario de las redes sociales.
 * Usa la librería HybridAuth
 *
 */
class YiiSocialConnect extends CApplicationComponent {

    const ERROR_NONE = 0;
    const ERROR_UNSPECIFIED = 1;
    const ERROR_GENERAL_CONFIGURATION = 2;
    const ERROR_PROVIDER_CONFIGURATION = 3;
    const ERROR_UNKNOWN_PROVIDER = 4;
    const ERROR_MISSING_CREDENTIALS = 5;
    const ERROR_AUTHENTIFICATION_FAILED = 6;
    const ERROR_REQUEST_FAILED = 7;
    const ERROR_NOT_CONNECTED = 8;
    const ERROR_FEATURE_NOT_SUPPORTED = 9;

    /**
     * @var Hybrid_Auth
     */
    private $_hybridAuth;

    /**
     * @var array Lista y configuración de las redes sociales
     */
    public $providers;

    /**
     * Configuración para Hybrid_Auth
     */
    public $callbackUrl, $debug_mode, $debug_file;

    /**
     * @var integer código de error. Si hay algún error, el código de error será distinto de 0.
     */
    public $errorCode = self::ERROR_UNSPECIFIED;

    /**
     * @var 
     */
    public $userProfile = NULL;

    /**
     * Inicialización del componente
     */
    public function init() {
        $this->registerScripts();
        parent::init();
    }

    /**
     * Incluir los ficheros de HybridAuth
     */
    public function createHybridAuth() {
        $this->_hybridAuth = new Hybrid_Auth($this->getConfig());
    }

    /**
     * Incluir los ficheros de HybridAuth
     */
    public function registerScripts() {
        require dirname(__FILE__) . '/vendors/Hybrid/Auth.php';
        require dirname(__FILE__) . '/vendors/Hybrid/Endpoint.php'; //callback
    }

    /**
     * Devuelve un array con la configuracion adaptada a HybridAuth
     * @return array configuración
     */
    public function getConfig() {
        $config = array(
            'baseUrl' => Yii::app()->getBaseUrl(true),
            'base_url' => Yii::app()->createAbsoluteUrl($this->callbackUrl), // URL for Hybrid_Auth callback
            'providers' => $this->providers,
        );
        if ($this->debug_mode) {
            $config['debug_file'] = $this->debug_file;
            $config['debug_mode'] = $this->debug_mode;
        }
        return $config;
    }

    public function callback() {
        Hybrid_Endpoint::process();
    }

    /**
     * Carga el perfil de un usuario de la red social indicada en el parámetro @param $provider
     * El perfil está en la propiedad $userProfile.
     * Si hay algún error, está en la propiedad $errorCode.
     * @param $provider string nombre de la red social (Twitter, Linkedin, Facebook)
     * @return boolean
     */
    public function loadUserProfile($provider) {
        $this->userProfile = NULL;

        if (!array_key_exists($provider, $this->providers)) {
            $this->errorCode = self::ERROR_UNKNOWN_PROVIDER;
        } else {
            $this->createHybridAuth();
            try {
                $social = $this->_hybridAuth->authenticate($provider);
                $this->userProfile = $social->getUserProfile();
                $social->logout();
                $this->errorCode = self::ERROR_NONE;
            } catch (Exception $e) {
                switch ($e->getCode()) {
                    case 0 :
                        $this->errorCode = self::ERROR_UNSPECIFIED;
                        break;
                    case 1 :
                        $this->errorCode = self::ERROR_GENERAL_CONFIGURATION;
                        break;
                    case 2 :
                        $this->errorCode = self::ERROR_PROVIDER_CONFIGURATION;
                        break;
                    case 3 :
                        $this->errorCode = self::ERROR_UNKNOWN_PROVIDER;
                        break;
                    case 4 :
                        $this->errorCode = self::ERROR_MISSING_CREDENTIALS;
                        break;
                    case 5 :
                        $this->errorCode = self::ERROR_AUTHENTIFICATION_FAILED;
                        break;
                    case 6 :
                        $this->errorCode = self::ERROR_REQUEST_FAILED;
                        $social->logout();
                        break;
                    case 7 :
                        $this->errorCode = self::ERROR_NOT_CONNECTED;
                        $social->logout();
                        break;
                    case 8 :
                        $this->errorCode = self::ERROR_FEATURE_NOT_SUPPORTED;
                        break;
                }
            }
        }

        if ($this->errorCode)
            Yii::log($this->getErrorMessage(), CLogger::LEVEL_TRACE);

        return !$this->errorCode;
    }

    /**
     * Devuelve el texto dek mensaje de error asociado al error que hay en la propiedad errorCode.
     * @return string mensaje de error
     */
    public function getErrorMessage() {
        $message = '';
        switch ($this->errorCode) {
            case self::ERROR_UNSPECIFIED:
                $message = "Unspecified error.";
                break;
            case self::ERROR_GENERAL_CONFIGURATION:
                $message = "Hybriauth configuration error.";
                break;
            case self::ERROR_PROVIDER_CONFIGURATION:
                $message = "Provider not properly configured.";
                break;
            case self::ERROR_UNKNOWN_PROVIDER:
                $message = "Unknown or disabled provider.";
                break;
            case self::ERROR_MISSING_CREDENTIALS:
                $message = "Missing provider application credentials.";
                break;
            case self::ERROR_AUTHENTIFICATION_FAILED:
                $message = "Authentification failed.";
                break;
            case self::ERROR_REQUEST_FAILED:
                $message = "User profile request failed.";
                break;
            case self::ERROR_NOT_CONNECTED:
                $message = "User not connected to the provider.";
                break;
            case self::ERROR_FEATURE_NOT_SUPPORTED:
                $message = "Provider does not support this feature.";
                break;
        }
        return $message;
    }

}

?>
