Custom Field not available for all callback instances (PHP)

TylerHanavan

New member
I am developing an add-on for my Xenforo-enabled website that changes the user's avatar based on a custom field they input in the Preferences section of their profile.

The custom field is "mcusername". If the user has inputted something in this field, their avatar image will be linked to "https://minotar.net/avatar/$mcusername" (with $mcusername replaced with the custom field) and if they do not have the custom field inputted, the avatar image will be linked to "https://minotar.net/avatar/Steve".

User's without the custom field "mcusername" should display this image
Steve


I was able to find some code on Xenforo and modify it to fit my needs

I have a callback for init_dependencies with that calls the following function

PHP:
    public static function init(XenForo_Dependencies_Abstract $dependencies, array $data)
    {
       
        XenForo_Template_Helper_Core::$helperCallbacks ['avatar'] = array('minecraftUsername_helpers', 'helperAvatarUrl');
        XenForo_Template_Helper_Core::$helperCallbacks ['avatarhtml'] = array('minecraftUsername_helpers', 'helperAvatarHtml');
       
    }

The above method then uses the following two helper methods:

PHP:
public static function helperAvatarHtml(array $user, $img, array $attributes = array(), $content = '')
    {
      
        $size = strtolower($attributes['size']);
      
        if($size == 's') {
          
            $urlSize = '/48';
          
        }
      
        if($size == 'm') {
          
            $urlSize = '/96';
          
        }
      
        $mcusername = $user['customFields']['mcusername'];
      
        if(isset($mcusername) && !empty($mcusername)) {
          
            $src = "https://minotar.net/avatar/$mcusername";
          
        } else {
          
            $src = "https://minotar.net/avatar/Steve";
      
        }

        $href = XenForo_Template_Helper_Core::getUserHref($user, $attributes);

        if ($img)
        {
            $username = htmlspecialchars($user['username']);
            $dimension = XenForo_Model_Avatar::getSizeFromCode($size);
          
            $image = "<img src=\"{$src}$urlSize\" width=\"{$dimension}\" height=\"{$dimension}\" alt=\"{$username}\" />";
        }
        else
        {
            $text = (empty($attributes['text']) ? '' : htmlspecialchars($attributes['text']));

            $image = "<span class=\"img {$size}\" style=\"background-image: url('{$src}$urlSize')\">{$text}</span>";
        }

        $class = (empty($attributes['class']) ? '' : ' ' . htmlspecialchars($attributes['class']));

        unset($attributes['user'], $attributes['size'], $attributes['img'], $attributes['text'], $attributes['class']);

        $attribs = XenForo_Template_Helper_Core::getAttributes($attributes);

        if ($content !== '')
        {
            $content = " {$content}";
        }

        return "<a{$href} class=\"avatar Av{$user['user_id']}{$size}{$class}\"{$attribs} data-avatarhtml=\"true\">{$image}{$content}</a>";
    }
  
  
    public static function helperAvatarUrl($user, $size, $forceType = null, $canonical = false)
    {
        if (!is_array($user))
        {
            $user = array();
        }

        if ($forceType)
        {
            switch ($forceType)
            {
                case 'default':
                case 'custom':
                    break;

                default:
                    $forceType = null;
                    break;
            }
        }
      
        $size = strtolower($attributes['size']);
      
        if($size == 's') {
          
            $urlSize = '/48';
          
        }
      
        if($size == 'm') {
          
            $urlSize = '/96';
          
        }
      
        $mcusername = $user['customFields']['mcusername'];
      
        if(isset($mcusername) && !empty($mcusername)) {
          
            $src = "https://minotar.net/avatar/$mcusername$urlSize";
          
        } else {
          
            $src = "https://minotar.net/avatar/Steve$urlSize";
      
        }

        return htmlspecialchars($src);
    }

The above code does work for some parts of the site, but other parts don't appear to work.

Working:
5eca0869eea0184d7c5b127696224186.png

f2d411512c47a8dc3ad148109380a1c7.png

36a5842b7ca8b952b24fe8450452530b.png
Not Working:
6dcd158814fcfb71892d45c956737aaf.png

f023f9be3b7e135f768cd0a234d1228b.png
More things I will note, it seems to be that $user['customFields'] is not defined for the sections of images in the "Not Working" spoiler. Another pattern I've noticed is that all the images displaying my "default avatar" seem to be the small versions of the images. I'm not sure why.
 
I am developing an add-on for my Xenforo-enabled website that changes the user's avatar based on a custom field they input in the Preferences section of their profile.

The custom field is "mcusername". If the user has inputted something in this field, their avatar image will be linked to "https://minotar.net/avatar/$mcusername" (with $mcusername replaced with the custom field) and if they do not have the custom field inputted, the avatar image will be linked to "https://minotar.net/avatar/Steve".

User's without the custom field "mcusername" should display this image
Steve


I was able to find some code on Xenforo and modify it to fit my needs

I have a callback for init_dependencies with that calls the following function

PHP:
    public static function init(XenForo_Dependencies_Abstract $dependencies, array $data)
    {
      
        XenForo_Template_Helper_Core::$helperCallbacks ['avatar'] = array('minecraftUsername_helpers', 'helperAvatarUrl');
        XenForo_Template_Helper_Core::$helperCallbacks ['avatarhtml'] = array('minecraftUsername_helpers', 'helperAvatarHtml');
      
    }

The above method then uses the following two helper methods:

PHP:
public static function helperAvatarHtml(array $user, $img, array $attributes = array(), $content = '')
    {
     
        $size = strtolower($attributes['size']);
     
        if($size == 's') {
         
            $urlSize = '/48';
         
        }
     
        if($size == 'm') {
         
            $urlSize = '/96';
         
        }
     
        $mcusername = $user['customFields']['mcusername'];
     
        if(isset($mcusername) && !empty($mcusername)) {
         
            $src = "https://minotar.net/avatar/$mcusername";
         
        } else {
         
            $src = "https://minotar.net/avatar/Steve";
     
        }

        $href = XenForo_Template_Helper_Core::getUserHref($user, $attributes);

        if ($img)
        {
            $username = htmlspecialchars($user['username']);
            $dimension = XenForo_Model_Avatar::getSizeFromCode($size);
         
            $image = "<img src=\"{$src}$urlSize\" width=\"{$dimension}\" height=\"{$dimension}\" alt=\"{$username}\" />";
        }
        else
        {
            $text = (empty($attributes['text']) ? '' : htmlspecialchars($attributes['text']));

            $image = "<span class=\"img {$size}\" style=\"background-image: url('{$src}$urlSize')\">{$text}</span>";
        }

        $class = (empty($attributes['class']) ? '' : ' ' . htmlspecialchars($attributes['class']));

        unset($attributes['user'], $attributes['size'], $attributes['img'], $attributes['text'], $attributes['class']);

        $attribs = XenForo_Template_Helper_Core::getAttributes($attributes);

        if ($content !== '')
        {
            $content = " {$content}";
        }

        return "<a{$href} class=\"avatar Av{$user['user_id']}{$size}{$class}\"{$attribs} data-avatarhtml=\"true\">{$image}{$content}</a>";
    }
 
 
    public static function helperAvatarUrl($user, $size, $forceType = null, $canonical = false)
    {
        if (!is_array($user))
        {
            $user = array();
        }

        if ($forceType)
        {
            switch ($forceType)
            {
                case 'default':
                case 'custom':
                    break;

                default:
                    $forceType = null;
                    break;
            }
        }
     
        $size = strtolower($attributes['size']);
     
        if($size == 's') {
         
            $urlSize = '/48';
         
        }
     
        if($size == 'm') {
         
            $urlSize = '/96';
         
        }
     
        $mcusername = $user['customFields']['mcusername'];
     
        if(isset($mcusername) && !empty($mcusername)) {
         
            $src = "https://minotar.net/avatar/$mcusername$urlSize";
         
        } else {
         
            $src = "https://minotar.net/avatar/Steve$urlSize";
     
        }

        return htmlspecialchars($src);
    }

The above code does work for some parts of the site, but other parts don't appear to work.

Working:
5eca0869eea0184d7c5b127696224186.png

f2d411512c47a8dc3ad148109380a1c7.png

36a5842b7ca8b952b24fe8450452530b.png
Not Working:
6dcd158814fcfb71892d45c956737aaf.png

f023f9be3b7e135f768cd0a234d1228b.png
More things I will note, it seems to be that $user['customFields'] is not defined for the sections of images in the "Not Working" spoiler. Another pattern I've noticed is that all the images displaying my "default avatar" seem to be the small versions of the images. I'm not sure why.

The user array passed to the avatar helper is occasionally not the full array, and may not contain certain extra data such as custom fields.

Liam
 
In reality your only option is to fetch the custom fields in the avatar method.

That will of course add queries to page views, however.

Liam
 
I feel like the way to do this will be to actually request this information at registration then actually download and save the image as their avatar. This will drastically reduce queries as the info will be loaded as an avatar.

The only caveat is you'll need to have it coded for you or code it yourself.
 
I've decided to opt for just querying the database. This is producing a new error issue.

Here's my code:

Code:
    if(!isset($mcusername) && empty($mcusername)) { //Custom field data was not passed
   
        $db = XenForo_Application::get('db');
        $mcusername = $db->fetchRow("SELECT field_value FROM xf_user_field_value WHERE (user_id=\"$id\" AND field_id=\"mcusername\")");
   
    }

Whenever I do this, ALL avatars that the custom field data was not passed to end up being the same image regardless of the user_id.

Nevermind. The issue was $mcusername was an Array instead of a string.

Thanks for the help everyone.
 
Last edited:
Back
Top Bottom