phpfacebookserializationopencart2.x

PHP : Serialization of a closure is not allowed


The whole scenario is that I have added facebook login extension in my opencart store , everything works fine when a new user clicks login with facebook add email and password and clicks login then comes a confirm login dialog which has two buttons "cancel" and "login" if user clicks login it takes the user to my store but when user clicks "cancel" it should take the user back to the login page at my store but instead it gives the error "Fatal error : uncaught exception with a message serialization of closure is not allowed
which is for this line "$_SESSION["HA::STORE"][$key] = serialize($value); I am using the following function which contains this line :

public function set( $key, $value)
    {
        $key = strtolower( $key );

        $_SESSION["HA::STORE"][$key] = serialize($value);
    }

I have tried this var_dump(serialize($value)); and it returns a string How can I serialize this? I have searched for it but not find any helpful solution

UPDATE :

function login()
    {
        Hybrid_Logger::info( "Enter Hybrid_Provider_Adapter::login( {$this->id} ) " );

        if( ! $this->adapter ){
            throw new Exception( "Hybrid_Provider_Adapter::login() should not directly used." );
        }

        // clear all unneeded params
        foreach( Hybrid_Auth::$config["providers"] as $idpid => $params ){
            Hybrid_Auth::storage()->delete( "hauth_session.{$idpid}.hauth_return_to"    );
            Hybrid_Auth::storage()->delete( "hauth_session.{$idpid}.hauth_endpoint"     );
            Hybrid_Auth::storage()->delete( "hauth_session.{$idpid}.id_provider_params" );
        }

        // make a fresh start
        $this->logout();

        # get hybridauth base url
        $HYBRID_AUTH_URL_BASE = Hybrid_Auth::$config["base_url"];

        # we make use of session_id() as storage hash to identify the current user
        # using session_regenerate_id() will be a problem, but ..
        $this->params["hauth_token"] = session_id();

        # set request timestamp
        $this->params["hauth_time"]  = time();

        # for default HybridAuth endpoint url hauth_login_start_url
        #   auth.start  required  the IDp ID
        #   auth.time   optional  login request timestamp
        $this->params["login_start"] = $HYBRID_AUTH_URL_BASE . ( strpos( $HYBRID_AUTH_URL_BASE, '?' ) ? '&' : '?' ) . "hauth.start={$this->id}&hauth.time={$this->params["hauth_time"]}";

        # for default HybridAuth endpoint url hauth_login_done_url
        #   auth.done   required  the IDp ID
        $this->params["login_done"]  = $HYBRID_AUTH_URL_BASE . ( strpos( $HYBRID_AUTH_URL_BASE, '?' ) ? '&' : '?' ) . "hauth.done={$this->id}";

        Hybrid_Auth::storage()->set( "hauth_session.{$this->id}.hauth_return_to"    , $this->params["hauth_return_to"] );
        Hybrid_Auth::storage()->set( "hauth_session.{$this->id}.hauth_endpoint"     , $this->params["login_done"] ); 
        Hybrid_Auth::storage()->set( "hauth_session.{$this->id}.id_provider_params" , $this->params );

        // store config to be used by the end point 
        Hybrid_Auth::storage()->config( "CONFIG", Hybrid_Auth::$config );

        // move on
        Hybrid_Logger::debug( "Hybrid_Provider_Adapter::login( {$this->id} ), redirect the user to login_start URL." );

        Hybrid_Auth::redirect( $this->params["login_start"] );
    }

In the function_login , set() is called by this :

Hybrid_Auth::storage()->set( "hauth_session.{$this->id}.hauth_return_to"    , $this->params["hauth_return_to"] );
        Hybrid_Auth::storage()->set( "hauth_session.{$this->id}.hauth_endpoint"     , $this->params["login_done"] ); 
        Hybrid_Auth::storage()->set( "hauth_session.{$this->id}.id_provider_params" , $this->params );

Solution

  • I'm guessing you are passing or getting passed a closure as the $value parameter of set().

    You need to either check for and ignore closures using reflection

    public function set( $key, $value)
    {
        if (is_object($value)) {
            try {
                $reflection = new ReflectionFunction($value);
                if ($reflection->isClosure()) {
                    //Trigger a E_USER_NOTICE if you want to avoid silently failing
                    trigger_error("You cannot pass a closure as the second parameter of set()");
                    return; // Do nothing else
                }
            } catch (\ReflectionException $e) {
                // Catch the exception thrown if $value is not a closure
            }
        }
        $key = strtolower( $key );
    
        $_SESSION["HA::STORE"][$key] = serialize($value);
    }
    

    Or you can catch and ignore the exception:

    function set( $key, $value)
    {
        $key = strtolower( $key );
        try{
            $_SESSION["HA::STORE"][$key] = serialize($value);
        } catch (\Exception $e) {
            // Catch the exception thrown and handle it however you want
        }
    }
    

    Or look at this github project for serializing closures