XF 2.1 Class Extension Issue - extending $xf.visitor

i_n_k

Member
I've been trying to figure this out but can't seem to make any progress.

In XF1, if I wanted to add an active variable to the $visitor group, I added a Listener and then the following code:

PHP:
if (!class_exists('Demo_Listener')){
class Demo_Listener {
 
    public static function visitor_setup(XenForo_Visitor &$visitor)
    {

    $visitor["my_variable"] = $data_for_my_variable;

    }
}
}

And that worked great. But obviously in XF2, things are quite different and I haven't been able to solve this yet.

I've been working with the following as a class extension:

PHP:
namespace AddOn;

use XF\Entity\User;

class User extends XFCP_User
{

    public static function getStructure(Structure $structure)
    {
        // Query for $variable with data
     
        $structure = parent::getStructure($structure);
     
        $structure->getters['my_selection'] = ['getter' => $variable , 'cache' => true];
       
        return $structure;
    }
}

And "my_selection" is not being added to the available array fields.

I've gone over this quite a few times and I feel like I have a reasonable grasp on things. The sample for the "hello world" worked and that at least means that I have things set correctly on the admin side, but I'm clearly doing something wrong where when it comes to adding something into the structure to hopefully use it as $xf.visitor.my_selection, it isn't adding it for me to pull it within the template:

Needless to say, any guidance you can provide is appreciated.
 
Last edited:

TickTackk

Well-known member
PHP:
        $structure->getters = [
            'my_selection' =>
            $variable,
        ];
You are completely overriding the available getters. If you were to add my_selection as a getter then you would also need to add getMySelection method to the entity which would return whatever my_selection should be returning. So something like this:
PHP:
    public function getMySelection()
    {
        return 'boo-moo';
    }
    ...
    public static function getStructure(EntityStructure $structure)
    {
        $structure = parent::getStructure($structure);

        $structure->getters['my_selection'] = true;

        return $structure;
    }
Note that true stands for caching the value after initial call.
 

i_n_k

Member
PHP:
        $structure->getters = [
            'my_selection' =>
            $variable,
        ];
You are completely overriding the available getters. If you were to add my_selection as a getter then you would also need to add getMySelection method to the entity which would return whatever my_selection should be returning. So something like this:
PHP:
    public function getMySelection()
    {
        return 'boo-moo';
    }
    ...
    public static function getStructure(EntityStructure $structure)
    {
        $structure = parent::getStructure($structure);

        $structure->getters['my_selection'] = true;

        return $structure;
    }
Note that true stands for caching the value after initial call.
I was updating my post right before you replied, as the code (which is obviously for a support question) was just a sample and I realized it would overwrite the array based on a similar question by someone previously:

PHP:
namespace AddOn;

use XF\Entity\User;

class User extends XFCP_User
{

    public static function getStructure(Structure $structure)
    {
        // Query for $variable with data
  
        $structure = parent::getStructure($structure);
  
        $structure->getters['my_selection'] = ['getter' => $variable , 'cache' => true];
    
        return $structure;
    }
}

Hopefully, this makes more sense. Sorry about that.
 
Last edited:

TickTackk

Well-known member
PHP:
['getter' => $variable
That wouldn't work again as you have not declared $variable and even if you declare $variable that would need to be the value of the method that would be called which will make the query you are looking to make and then return value accordingly.
 

i_n_k

Member
PHP:
['getter' => $variable
That wouldn't work again as you have not declared $variable and even if you declare $variable that would need to be the value of the method that would be called which will make the query you are looking to make and then return value accordingly.
I had just commented it out for the sake of it, but it would essentially be as below:

PHP:
namespace AddOn;

use XF\Entity\User;

class User extends XFCP_User
{

    public static function getStructure(Structure $structure)
    {
        $variable = "myData";
  
        $structure = parent::getStructure($structure);
  
        $structure->getters['my_selection'] = ['getter' => $variable , 'cache' => true];
    
        return $structure;
    }
}

So based on your previous response, it's obvious that when trying to define a value to 'my_selection', this clearly isn't the way to do it.

Again, going back to my first post, in XF1, it was just a matter of adding the listener and defining the $visitor['whatever'] = 'dafsjdkfl';

With a class extension, I don't quite seem to understand it the same way and based off some previous questions I've seen others post, I thought the above was close to what I was trying to achieve. But based on what you've said so far, it appears how I'm trying to define ['my_selection'] isn't correct...?
 

i_n_k

Member
And I'm basing this off of this post, which Chris D said should work, but I haven't had success with it yet:


So I'm just trying to get a better grasp on this as it's the last step I need to complete before moving from XF1 to XF2
 

i_n_k

Member
Just to further clarify, I do know that the purpose of the Class Extension is to add to the additional values in the "getters" array in User.php:

PHP:
$structure->getters = [
            'PermissionSet' => [
                'getter' => true,
                'cache' => true
            ],
            'permission_combination_id' => false,
            'is_super_admin' => true,
            'last_activity' => true,
            'email_confirm_key' => true,
            'warning_count' => true
        ];

My question is to try and figure out where my error is in defining 'my_selection' and assigning a value to it so that I can use it in xf.visitor.my_selection within the template and have it either output the value, be used in an 'if/else' statement, etc.
 

i_n_k

Member
Got it - this is solved. Your tip about what method to call made more sense when I finally got it to throw an error.

Here's the final:

PHP:
namespace Addon;

class User extends XFCP_User
{
public static function myFunction(){
  
    $boo = "boo";
  
    return($boo);
}

   public static function getStructure($structure)

    {
      $structure = parent::getStructure($structure);

         $structure->getters['my_variable'] = ['getter' => 'myFunction', 'cache' => true];     
    
        return $structure;
    }
}

So using $xf.visitor.my_variable now outputs "boo" as needed.

This is using the following settings in Add Class Extension:

Base class name: XF\Entity\User
Extension class name: Addon\User

(Addon is the name you're using for your Add on for this, with User being the User.php file with the above code.)

Hope this helps someone else, and thank you for your reply which nudged me just enough to be able to figure it out :)
 

i_n_k

Member
One other note, the getStructure(EntityStructure $structure) threw an error:

"Declaration of AddOn\User::getStructure(AddOn\EntityStructure $structure) should be compatible with XF\Entity\User::getStructure"

getStructure(Structure $structure) also threw the same error.

So if anyone else sees that, apparently that's a conflict and the final code I posted did work.
 

Kirby

Well-known member
PHP:
public static function getStructure(\XF\Mvc\Entity\Structure $structure)
is the correct sigature.

Or if you have the use statement
PHP:
use XF\Mvc\Entity\Structure;

you can shorten it to
PHP:
public static function getStructure(Structure $structure)

This is really just basic namespacing.
 

i_n_k

Member
One quick note on this - this works as expected but I've found it conflicts with other add-ons. However, changing the order to 20 (from the default 10) took care of the issue and everything works just fine. Just discovered this over the weekend and wanted to follow up in the event anyone else has a similar issue.
 
Top