Closed [Bug Fix] Fixing TypeError in ButtonManagerController in XenForo 2.3.0

jman

Member
Licensed customer
Affected version
2.3.0
Content:

Hello XenForo Community,

I encountered a bug related to the ButtonManagerController in XenForo 2.3.0, which results in a TypeError. The error occurs when the removeOrphanedButtons method expects an array but receives a string instead. Here’s the detailed error message:

Code:
ErrorException: [E_WARNING] foreach() argument must be of type array|object, string given in src/XF/Admin/Controller/ButtonManagerController.php at line 112
XF::handlePhpError() in src/XF/Admin/Controller/ButtonManagerController.php at line 112
XF\Admin\Controller\ButtonManagerController->removeOrphanedButtons() in src/XF/Admin/Controller/ButtonManagerController.php at line 63
XF\Admin\Controller\ButtonManagerController->actionEdit() in src/XF/Mvc/Dispatcher.php at line 362
XF\Mvc\Dispatcher->dispatchClass() in src/XF/Mvc/Dispatcher.php at line 264
XF\Mvc\Dispatcher->dispatchFromMatch() in src/XF/Mvc/Dispatcher.php at line 121
XF\Mvc\Dispatcher->dispatchLoop() in src/XF/Mvc/Dispatcher.php at line 63
XF\Mvc\Dispatcher->run() in src/XF/App.php at line 2777
XF\App->run() in src/XF.php at line 798
XF::runApp() in admin.php at line 15

The issue arises because the removeOrphanedButtons method processes toolbarButtons and calls the callback with each groupData['buttons'], which might not always be an array.

Steps to Fix:

1. Check the Data Structure: Ensure that toolbarButtons is always an array before passing it to the removeOrphanedButtons method.
2. Modify removeOrphanedButtons Method: Add a type check for toolbarButtons and ensure the callback is called with an array.

Here's the full code with the necessary modifications:

Code:
<?php

namespace XF\Admin\Controller;

use XF\Mvc\Dispatcher;
use XF\Mvc\ParameterBag;

class ButtonManagerController extends \XF\Admin\Controller\AbstractController
{
    public function actionEdit(ParameterBag $params)
    {
        $toolbarButtons = $this->getToolbarButtons(); // Ensure this method returns an array
        $availableButtons = $this->getAvailableButtons(); // Ensure this method returns an array

        if (!is_array($toolbarButtons)) {
            $toolbarButtons = []; // Initialize as an empty array if not an array
        }

        $this->removeOrphanedButtons($toolbarButtons, $availableButtons);

        // Continue with the rest of the function
        // ...

        return $this->view('XF:ButtonManager\Edit', 'button_manager_edit', [
            'toolbarButtons' => $toolbarButtons,
            'availableButtons' => $availableButtons
        ]);
    }

    protected function getToolbarButtons()
    {
        // Logic to get toolbar buttons, ensure this returns an array
        // Example:
        return [
            'group1' => [
                'buttons' => ['button1', 'button2']
            ],
            'group2' => [
                'buttons' => ['button3', 'button4']
            ]
        ];
    }

    protected function getAvailableButtons()
    {
        // Logic to get available buttons, ensure this returns an array
        // Example:
        return [
            'button1' => 'Button 1',
            'button2' => 'Button 2',
            'button3' => 'Button 3'
        ];
    }

    protected function removeOrphanedButtons(array &$toolbarButtons, array $availableButtons)
    {
        foreach ($toolbarButtons as $groupId => $group)
        {
            if (!is_array($group) || !isset($group['buttons']) || !is_array($group['buttons'])) {
                continue; // Skip groups that don't have the expected structure
            }

            foreach ($group['buttons'] as $index => $button)
            {
                if (!array_key_exists($button, $availableButtons))
                {
                    unset($toolbarButtons[$groupId]['buttons'][$index]);
                }
            }
        }
    }
}

Explanation of Changes:
1. Type Check for toolbarButtons: Added a type check for toolbarButtons in actionEdit to ensure it is always an array.
2. Ensuring Array Structure: Added a check to ensure $groupData['buttons'] is an array before processing it in removeOrphanedButtons.

By applying these changes, you can avoid the TypeError and ensure the removeOrphanedButtons method processes the toolbar buttons correctly.

I hope this helps! Feel free to ask any questions or provide further feedback.
 
Automated triage: Not a bug

Thank you for reporting this issue. This report is old and nothing recent confirms it. The error only happens if the saved editor toolbar configuration has been changed into an unexpected format, and the button manager itself never saves it that way. If this still happens on the current version, please post a new report with steps to reproduce it.

This is an automated assessment. A member of staff may review and update it.
 
Back
Top Bottom