• This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn more.
Profile Tab Manager

Profile Tab Manager 1.0.1

No permission to download
Create new profile tabs in the user's profiles.

ArnyVee

Well-known member
#2
Hey there Fuhrmann, I love the idea of adding my own tab with the ability to display some "Favorites" of the members.

So, for example, I want to create some custom user profile fields where the member selects their "Favorite Movie" and then an image of the movie is displayed. Then, "Favorite Song" after that based on their selection from a drop down menu within the personal preferences area.

Can you detail as to how we would do something like that?
 
#3
I'm also curious about how I can add some fields to the new tab where a select portion of my users can share like contact details etc.

B.t.w. doesn´t seem to work with latest XenForo... (had to change persmissions to include Registered)
 
#5
I wonder if anyone managed to find out how to display the profile owners username for example instead of the visitor's one?
 
#6
I wonder if anyone managed to find out how to display the profile owners username for example instead of the visitor's one?
The dirty method that I used was using the request URL:

Code:
        //Get URL requestions
        $request = new Zend_Controller_Request_Http;
        $request = $request->get('REQUEST_URI');
        $request = explode('/', $request);
 
        $request = explode('.', $request[2]);
 
        $user_id = $request[0];
 
    // Got the username and not ID
        if( !(is_numeric($user_id)) )
        {
          $userModel = XenForo_Model::create('XenForo_Model_User');
          $user = $userModel->getUsersByNames(Array($user_id));
          $user = $userModel->prepareUser($user);
          $user = reset($user);
          $user_id = $user['user_id'];
        }
 
#7
Managed to get an answer from Chris Deeming which was very useful so I am sharing it. He said since all the values are already in the member template, you can simply use $user.username to get the profile username. Maybe this will help you also as it saves some extra code.

Thank you for your reply though!

Nelly
 
#10
Useful addon. Thank you.

One issue for me is the "Usergroup to applies the tab" seems to only take in to account the primary group, and not secondary groups.

For various reasons, all my users have to have Registered as their primary group, but I only want to apply my custom tab to certain secondary groups.

Not a show stopper, but if Furhmann is listening ...

-- hugh
 
#11
The dirty method that I used was using the request URL:
I ran in to the same issue, just couldn't find a neat way to get at the member info, even though I knwo it's already loaded "somewhere". Had to tweak that code example you gave a little, as it didn't seem to take the full URI in to account, with index.php? prepended.

Anyway, here's my function. What it does is load a list of sites that we support for our users, which is maintained in a custom profile table on the Joomla! side of our site. I need to display this list on the forums for "Support Staff", so the tab is configured to only be visible to that group.

We use jFusion for single sign on, so users share the same email in XF and J!. So I need to grab the profile owner's email, before loading up the site list from the J! database. I've included the J! specific stuff I use for loading the J! config, to grab the database connection details, in case anyone else is googling around for how to do this in XF.

This is all working nicely on my sandbox, and I'm about to put it in production on our live site.

PHP:
class ProfileTabManager_Callbacks_Sites extends XenForo_Application
{
 
    /**
    * Load the J! config.  Assumes that XF lives in a folder inside the main J!
    * root, which is the case on sandbox and live site.
    *
    * @return JConfig|boolean
    */
    static public function loadJoomlaConfig()
    {
        if (class_exists('JConfig', false))
        {
            return new JConfig();
        }
        else
        {
            // $$$ Is there a better way of getting XF's root dir?
            $xfRoot = dirname(__FILE__) . '/../../..';
       
            $JoomlaConfig =  $xfRoot . '/../configuration.php';
            if (file_exists($JoomlaConfig))
            {
                include($JoomlaConfig);
                if (class_exists('JConfig', false))
                {
                    return new JConfig();
                }
            }
        }
        return false;
    }
 
    /**
    * Create a db connection to the J! database.
    *
    * @param string $jConfig
    * @return boolean
    */
    private static function getJoomlaDb($jConfig = false)
    {
        $jConfig = self::loadJoomlaConfig();
        if ($jConfig !== false)
        {
            $zConfig = new Zend_Config(
                array(
                    'adapter' => 'mysqli',
                    'host' => $jConfig->host,
                    'username' => $jConfig->user,
                    'password' => $jConfig->password,
                    'dbname' => $jConfig->db,
                    'port' => '3306',
                    'charset' => 'utf8'
                )
            );
            return XenForo_Application::getInstance()->loadDb($zConfig);
        }
        return false;
    }
 
    /**
    * Little helper func to get a J! config setting
    *
    * @param string $name J! config setting name
    * @return boolean
    */
    static private function getJoomlaSetting($name)
    {
        $config = self::loadJoomlaConfig();
        if ($config !== false)
        {
            return $config->$name;
        }
        return false;
    }
 
    /**
    * The Meat Of The Thing
    *
    * Callback function for Profile Tab Manager, to build list of sites we provide
    * support for, from a custom table on our Joomla! database.  This will add
    * 'user_sites' to the view data for the profile tab.
    *
    * @return array  site list
    */
    public static function getSites()
    {
        /*
        * Set up default empty sites
        */
        $userSites = array();
   
        /**
        * There MUST be a simple way of getting the member details being viewed,
        * but I can't find it, so for now, do it by steam, by fetching the
        * raw request and parsing the name/id out of the query string.
        */
 
        $request = new Zend_Controller_Request_Http;
        $request = $request->get('REQUEST_URI');
        $request = explode('?', $request);
        $request = explode('/', $request[1]);
        /*
        * Quick sanity check to make sure we have a members/foo.x/ URI
        */
        if ($request[0] !== 'members' || count($request) < 2)
        {
            return $userSites;
        }
        $request = explode('.', $request[1]);
        $user_id = $request[0];
   
        /*
        * Well, we've got something that is probably a name or an ID!
        */
        if (!empty($user_id))
        {
            $userModel = XenForo_Model::create('XenForo_Model_User');
       
            /*
            * Use the appropriate method to look up the user, depending on
            * whether we have a string (username) or a number (ID)
            */
            if (!is_numeric($user_id))
            {
                $user = $userModel->getUsersByNames(Array($user_id));
            }
            else
            {
                $user = $userModel->getUsersByIds(Array($user_id));
            }
       
            /*
            * if it's not empty, we got our member user.  Yay!
            */
            if (!empty($user))
            {
                $user = $userModel->prepareUser($user);
                $user = reset($user);
           
                /*
                * Probably don't need to check for empty, but as we're going
                * to use it in a query, best to make sure.
                */
                if (!empty($user['email']))
                {
                    /*
                    * Get the Joomla DB instance
                    */
                    $db = self::getJoomlaDb();
                    if ($db !== false)
                    {
                        /*
                        * Find the J! user by keying on the email, relying on jFusion
                        * to be syncing those between XF and Joomla, and fetch that J!
                        * users site list from the fabrik_user_sites table
                        */
                        $query = "
                            SELECT *
                            FROM fabrik_user_sites AS s
                            LEFT JOIN " . self::getJoomlaSetting('dbprefix') . "users AS u ON u.id = s.user_id
                            WHERE u.email = " . $db->quote($user['email']) . "
                        ";
                        $user_sites = $db->fetchAll($query);
                    }
                }
            }
        }
   
        /*
        * Done.  Return the $user_sites array inside an array, as it's going to
        * get merged into the main view params array by the Tab manager
        */
        return array('user_sites' => $user_sites);
    }
}
Hope this helps somebody.

Oh, and of course, if someone has a better way of getting the member details, instead of doing it by steam by parsing the request string, PLEASE let me know!

-- hugh
 
#12
BTW, Furhman ... it would be useful if you could pass the existing $viewParams in to the callback, in addition to the $tabsTemplate array, as the $viewParams already contains a lot of useful info, like the member profile being viewed. So a small tweak on line 197 in the ProfileTabs.php data writer:

PHP:
                    $callBackParams = call_user_func_array(array($tabsTemplate['tab_callback_class'], $tabsTemplate['tab_callback_method']), array(array('tabsTemplate' => $tabsTemplate, 'viewParams' => $viewParams)));
Then instead of all that horrible URI parsing to get the profile owner in our callbacks, I could just grab the email (or whatever) with ...

PHP:
$profile_email = $params['viewParams']['user']['email'];
I suspect there may be a method I could use to grab the $viewParams as-is, I just can't work out how to do it. And as it's something I suspect would be useful to anyone writing a PHP tab callback, as knowing who's profile is being viewed is kind of fundamental, it would seem to make sense to pass that data to the callback.

-- hugh
 
#13
Hi Furhmann,

Thanks for the response to my PM, and for applying that suggested code change in your next release. I went ahead and made it locally to my copy of your code, so my getSites() function suddenly got a LOT simpler:

PHP:
    public static function getSites($params)
    {
        /*
        * Set up default empty sites
        */
        $userSites = array();
     
        /*
        * Get the email for the owner of the profile being viewed,
        * from the viewParams passed in to our callback by the tabs manager
        */
        $profile_email = $params['viewParams']['user']['email'];
     
        if (!empty($profile_email))
        {
            /*
            * Get the Joomla DB instance
            */
            $db = self::getJoomlaDb();
            if ($db !== false)
            {
                /*
                * Find the J! user by keying on the email, relying on jFusion
                * to be syncing those between XF and Joomla, and fetch that J!
                * users site list from the fabrik_user_sites table
                */
                $query = "
                    SELECT *
                    FROM fabrik_user_sites AS s
                    LEFT JOIN " . self::getJoomlaSetting('dbprefix') . "users AS u ON u.id = s.user_id
                    WHERE u.email = " . $db->quote($profile_email) . "
                ";
                $user_sites = $db->fetchAll($query);
            }
        }
     
        /*
        * Done.  Return the $user_sites array inside an array, as it's going to
        * get merged into the main view params array by the Tab manager
        */
        return array('user_sites' => $user_sites);
    }
-- hugh
 
#18
Has the problem of only looking at primary groups ever been solved? Makes it hard to apply this just to a certain secondary group...

Never mind. To answer my own question, I edited the following in library/ProfileTabManager/DataWriter/ProfileTabs.php:

Code:
    public function loadTemplateLinks(XenForo_Template_Abstract $template, $viewParams)
    {
        $visitor = XenForo_Visitor::getInstance();    
        $tabModel = $this->_getProfileTabsModel();
        //Get all tabs that are activy (only the links)
        $tabsLinks = $tabModel->getAllActiviesTabs();
        if ($tabsLinks)
        {
            foreach ($tabsLinks as $tabsTemplate)
            {
            if (!in_array($viewParams['user']['user_group_id'], explode(',',$tabsTemplate['tab_usergroups_exclude_id'])) &&
                    (!array_intersect(explode(',',$tabsTemplate['tab_usergroups_exclude_id']), explode(',', $viewParams['user']['secondary_group_ids']))))
                {

                    if (in_array($viewParams['user']['user_group_id'], explode(',',$tabsTemplate['tab_usergroups_id'])) ||
                    (array_intersect(explode(',',$tabsTemplate['tab_usergroups_id']), explode(',', $viewParams['user']['secondary_group_ids']))))

          {
                        $ourTemplate = $template->create($tabsTemplate['tab_template_link'], $template->getParams());                    
                        $rendered .= $ourTemplate->render();
                        $rendered = str_replace ('__tab__', $tabsTemplate['tab_title'], $rendered);
                    }
                }
            }
        }
        return $rendered;
    }
 
Last edited: