Skip to content
This repository has been archived by the owner on Nov 3, 2023. It is now read-only.

Frontenduser cannot be correctly extended due to getInstance bug #2969

Closed
ghost opened this issue Nov 29, 2011 · 10 comments
Closed

Frontenduser cannot be correctly extended due to getInstance bug #2969

ghost opened this issue Nov 29, 2011 · 10 comments
Assignees
Labels
Milestone

Comments

@ghost
Copy link

ghost commented Nov 29, 2011

The Frontenduser class cannot be correctly extended due to a bug in the implementation of getInstance method.

Current method line 173
self::$objInstance = new FrontendUser();

Corrected
self::$objInstance = new self();

This allows the extended class to be instantiated as the singleton, rather than FrontendUser class

when using ->import('Frontenduser', 'User') or ->import('myextendedFrontenduser')

The extended class is not correctly initialised by the framework without this method being changed.

For full conversation about why I think this is an error see the forum post here: [http://www.contao-community.org/viewtopic.php?f=9&t=2899]

--- Originally created by wal5hy on March 30th, 2011, at 01:04am (ID 2969)

@ghost ghost assigned leofeyer Nov 29, 2011
@ghost
Copy link
Author

ghost commented Nov 29, 2011

Ahhh....
wrote this far too late last night and when I woke up this morning realised I made a mistake in my code.....

this is not a bug.

But it remains true that FrontendUser is Extremely difficult to extend

--- Originally created by wal5hy on March 30th, 2011, at 10:33am

@leofeyer
Copy link
Member

How did you solve it finally?

--- Originally created on March 31st, 2011, at 11:41am

@ghost
Copy link
Author

ghost commented Nov 29, 2011

Haven't quite got round to it yet, but here's my thinking

class MyFrontendUser extends FrontendUser
{

    public static function getInstance()
    {
        if (

![](is_object(self::$objInstance))
        {
            self::$objInstance = new self();
        }
        elseif(get_class(self::$objInstance) )= get_called_class()){
            $newStaticObject = new self();
            $newStaticObject->setData(self::$objInstance->arrData);
            self::$objInstance = $newStaticObject;
        }

        return self::$objInstance;
    }

    protected function setCookie($strName, $varValue, $intExpires, $strPath='', $strDomain=null, $blnSecure=null)
    {
        $strDomain = (is_null($strDomain) ? '.mysite.com' : $strDomain );
        parent::setCookie($strName, $varValue, $intExpires, $strPath, $strDomain, $blnSecure);
    }

}

edit: struggling to get the code to format properly sorry

If FrontendUser is already initialised (which it is) then I replace it with MyFrontendUser, before doing that I pass the data across from the old class to the new
If somewhere else another piece of code import FrontendUser everything will carry on working as expected (unless I override all kinds of stuff)

Does this seem like the most logical approach? I really can't think of anything else.

Problems with this approach:
The framework imports FrontendUser elsewhere first on the next page load and so unintended things happen (like creating an additional top domain cookie (which stalls page load on some other subdomains ?))

Possible solutions:
in the same way that there is a page type array modify page types, create a user type array
add to backend/config/config.php
$GLOBALS['TL_UTY'] = array
(
'backend' => 'BackendUser',
'frontend' => 'FrontendUser'
);

solve my problem in particular
Add an extra setting $GLOBALS['TL_CONFIG']['cookie-domain']
edit System.php

protected function setCookie($strName, $varValue, $intExpires, $strPath='', $strDomain=null, $blnSecure=null)
{
    if (!strlen($strPath))
    {
        $strPath = '/';
    }

    $strDomain = (is_null($strDomain) ? $GLOBALS['TL_CONFIG']['cookie-domain'] : $strDomain );
    setcookie($strName, $varValue, $intExpires, $strPath, $strDomain, $blnSecure);
}

Other thoughts:

I also can't help but think that some of the postLogin and postLogout hook should be moved to FrontendUser rather than be in ModuleLogin and ModuleLogout
as I am writing my own login/logout module and it seems unneccessary to have to duplicate that code?
Also should there be a function added to functions.php which does all the looping required for the hooks?

--- Originally created by wal5hy on March 31st, 2011, at 12:35pm

@ghost
Copy link
Author

ghost commented Nov 29, 2011

Another option maybe to make FrontendUser interface and specify in a config file what class implements the interface

--- Originally created by wal5hy on April 1st, 2011, at 09:31am

@ghost
Copy link
Author

ghost commented Nov 29, 2011

Or maybe create a static var in FrontendUser called "className"

then change this to the name of the class to be instantiated in getInstance.

--- Originally created by wal5hy on April 1st, 2011, at 09:37am

@leofeyer
Copy link
Member

Did you define a getInstance() method in your child class?

--- Originally created on June 15th, 2011, at 01:27pm

@ghost
Copy link
Author

ghost commented Nov 29, 2011

yes, but since this line exists in index.php

line: 59 $this->import('FrontendUser', 'User');

the base class ( FrontendUser ) is being called before I can override functionality.

maybe a potential fix is this (changing FrontendUser.php )

public static function getInstance() { if (!is_object(self::$objInstance)) { self::$objInstance = new $GLOBALS['TL_USER']['frontend'](); } return self::$objInstance; }

Then in a config file add
$GLOBALS['TL_USER'] = array ( 'frontend' => 'FrontendUser', 'backend' => 'BackendUser' );

This means that any other module which uses $this->import('FrontendUser', 'User')
would be getting the same extended frontenduser class, therefore data would be consistent across a request.

--- Originally created by wal5hy on June 15th, 2011, at 02:58pm

@ghost
Copy link
Author

ghost commented Nov 29, 2011

I need this, too. Was it solved somehow, since you closed it, Leo?
Or should I just apply wal5hy's excellent (I think) suggestion to FrontendUser myself?

Cheers

--- Originally created by icarus on September 5th, 2011, at 02:43pm

@leofeyer
Copy link
Member

Implemented in 2fd7ffa.

--- Originally created on September 14th, 2011, at 12:51pm

@leofeyer
Copy link
Member

--- Originally completed on September 14th, 2011, at 12:51pm

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

1 participant