Reply to thread

Content:


Hello XenForo Community,


I encountered a bug related to the Giphy option configuration in XenForo 2.3.0, which results in a TypeError. The error occurs when the callback function in XF\Option\Giphy expects an array but receives a string instead. Here’s the detailed error message:


[CODE]

TypeError: XF\Option\Giphy::XF\Option\{closure}(): Argument #1 ($buttonSet) must be of type array, string given, called in /home/admin/domains/shadowcoders.net/public_html/src/XF/Option/Giphy.php on line 124 in src/XF/Option/Giphy.php at line 57

XF\Option\Giphy::XF\Option\{closure}() in src/XF/Option/Giphy.php at line 124

XF\Option\Giphy::updateToolbarButtons() in src/XF/Option/Giphy.php at line 56

XF\Option\Giphy::insertGiphyToolbarButton() in src/XF/Option/Giphy.php at line 47

XF\Option\Giphy::verifyOption() in src/XF/Entity/Option.php at line 217

XF\Entity\Option->verifyOptionValue() in src/XF/Mvc/Entity/Entity.php at line 836

XF\Mvc\Entity\Entity->_verifyValueCustom() in src/XF/Mvc/Entity/Entity.php at line 677

XF\Mvc\Entity\Entity->set() in src/XF/Mvc/Entity/Entity.php at line 612

XF\Mvc\Entity\Entity->__set() in src/XF/Repository/OptionRepository.php at line 120

XF\Repository\OptionRepository->updateOptions() in src/XF/Admin/Controller/OptionController.php at line 92

XF\Admin\Controller\OptionController->actionUpdate() 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

[/CODE]


The issue arises because the updateToolbarButtons 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 groupData['buttons'] is always an array before passing it to the callback function.

2. Modify updateToolbarButtons Method: Add a type check for editorToolbarConfig and ensure the callback is called with an array.


Here's the full code with the necessary modifications:


[CODE]

<?php


namespace XF\Option;


use XF\Entity\Option;

use XF\Repository\OptionRepository;


use function is_array;


class Giphy extends AbstractOption

{

    public static function verifyOption(&$value, Option $option)

    {

        if ($option->isInsert())

        {

            return true;

        }


        if (empty($value['enabled']))

        {

            if ($option->option_value['enabled'])

            {

                // just disabled

                static::removeGiphyToolbarButton();

            }


            return true;

        }


        if ($value['enabled'])

        {

            if (empty($value['api_key']))

            {

                $option->error(\XF::phrase('please_enter_value_for_required_field_x', ['field' => 'giphy[api_key]']), $option->option_id);

                return false;

            }


            if (!preg_match('/^[a-z0-9]{32}$/i', $value['api_key']))

            {

                $option->error(\XF::phrase('please_enter_a_valid_api_key'), $option->option_id);

                return false;

            }


            if (!$option->option_value['enabled'])

            {

                // just enabled

                static::insertGiphyToolbarButton();

            }

        }


        return true;

    }


    public static function insertGiphyToolbarButton()

    {

        static::updateToolbarButtons(

            function (array $buttonSet)

            {

                $insertPosition = null;

                foreach ($buttonSet as $k => $button)

                {

                    if ($button == 'xfSmilie')

                    {

                        $insertPosition = $k + 1;

                    }

                    else if ($button == 'xfInsertGif')

                    {

                        // already have it

                        $insertPosition = null;

                        break;

                    }

                }


                if ($insertPosition !== null)

                {

                    array_splice($buttonSet, $insertPosition, 0, ['xfInsertGif']);

                }


                return $buttonSet;

            }

        );

    }


    public static function removeGiphyToolbarButton()

    {

        static::updateToolbarButtons(

            function (array $buttonSet)

            {

                $newButtons = [];


                foreach ($buttonSet as $button)

                {

                    if ($button == 'xfInsertGif')

                    {

                        continue;

                    }


                    $newButtons[] = $button;

                }


                return $newButtons;

            }

        );

    }


    protected static function updateToolbarButtons(callable $buttonsCallback)

    {

        $toolbarButtons = \XF::options()->editorToolbarConfig;


        if (!is_array($toolbarButtons)) {

            throw new \InvalidArgumentException('Expected array for editorToolbarConfig, got ' . gettype($toolbarButtons));

        }


        foreach ($toolbarButtons as $type => &$group)

        {

            if (!is_array($group))

            {

                continue;

            }


            foreach ($group as &$groupData)

            {

                if (!is_array($groupData) || empty($groupData['buttons']))

                {

                    continue;

                }


                if (!is_array($groupData['buttons']))

                {

                    // Skip if buttons are not in array form

                    continue;

                }


                $groupData['buttons'] = $buttonsCallback($groupData['buttons']);

            }

        }


        \XF::repository(OptionRepository::class)->updateOption('editorToolbarConfig', $toolbarButtons);

    }

}

[/CODE]


Explanation of Changes:

1. verifyOption Method Signature: Ensured that verifyOption conforms to the expected usage in XenForo.

2. Type Check for editorToolbarConfig: Added a type check for editorToolbarConfig in updateToolbarButtons to ensure it is always an array.

3. Ensuring Array Structure: Added a check to ensure $groupData['buttons'] is an array before passing it to the callback function.


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


I hope this helps!  Feel free to ask any questions or provide further feedback


Back
Top Bottom