joomla / joomla-cms

Home of the Joomla! Content Management System
https://www.joomla.org
GNU General Public License v2.0
4.71k stars 3.64k forks source link

Submitting a form with subform causes Json_decode() error #39768

Closed Amelie-Mahild closed 1 year ago

Amelie-Mahild commented 1 year ago

Steps to reproduce the issue

Add a custom field of type subform to your contact form (Componants/Contacts/Fields - Mail) All subfields are of type "Text" Subform is repeatable Fill out the form and submit

Actual result

0 json_decode(): Argument #1 ($json) must be of type string, array given Call stack

Function Location

1 () JROOT/plugins/fields/subform/subform.php:125 2 json_decode() JROOT/plugins/fields/subform/subform.php:125 3 PlgFieldsSubform->onCustomFieldsBeforePrepareField() JROOT/libraries/src/Plugin/CMSPlugin.php:279 4 Joomla\CMS\Plugin\CMSPlugin->Joomla\CMS\Plugin{closure}() JROOT/libraries/vendor/joomla/event/src/Dispatcher.php:486 5 Joomla\Event\Dispatcher->dispatch() JROOT/libraries/src/Application/EventAware.php:107 6 Joomla\CMS\Application\WebApplication->triggerEvent() JROOT/administrator/components/com_fields/src/Helper/FieldsHelper.php:204 7 Joomla\Component\Fields\Administrator\Helper\FieldsHelper::getFields() JROOT/components/com_contact/src/Controller/ContactController.php:242 8 Joomla\Component\Contact\Site\Controller\ContactController->_sendEmail() JROOT/components/com_contact/src/Controller/ContactController.php:187 9 Joomla\Component\Contact\Site\Controller\ContactController->submit() JROOT/libraries/src/MVC/Controller/BaseController.php:672 10 Joomla\CMS\MVC\Controller\BaseController->execute() JROOT/libraries/src/Dispatcher/ComponentDispatcher.php:143 11 Joomla\CMS\Dispatcher\ComponentDispatcher->dispatch() JROOT/components/com_contact/src/Dispatcher/Dispatcher.php:46 12 Joomla\Component\Contact\Site\Dispatcher\Dispatcher->dispatch() JROOT/libraries/src/Component/ComponentHelper.php:355 13 Joomla\CMS\Component\ComponentHelper::renderComponent() JROOT/libraries/src/Application/SiteApplication.php:200 14 Joomla\CMS\Application\SiteApplication->dispatch() JROOT/libraries/src/Application/SiteApplication.php:241 15 Joomla\CMS\Application\SiteApplication->doExecute() JROOT/libraries/src/Application/CMSApplication.php:294 16 Joomla\CMS\Application\CMSApplication->execute() JROOT/includes/app.php:61 17 require_once() JROOT/index.php:32

System information (as much as possible)

PHP Built On Linux info 3.0 #1337 SMP Tue Jan 01 00:00:00 CEST 2000 all GNU/Linux Database Type mysql Database Version 5.7.38-log Database Collation utf8_general_ci Database Connection Collation utf8mb4_general_ci Database Connection Encryption None Database Server Supports Connection Encryption Yes PHP Version 8.0.27 Web Server Apache WebServer to PHP Interface cgi-fcgi Joomla! Version Joomla! 4.2.7 Stable [ Uaminifu ] 31-January-2023 15:00 GMT User Agent Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36

Additional comments

Changing the following function in JROOT/plugins/fields/subform/subform.php:125 "fixes" the problem.

public function onCustomFieldsBeforePrepareField($context, $item, $field) { // Check if the field should be processed by us if (!$this->isTypeSupported($field->type)) { return; }

    // EDITED BY AMELIE because of json_decode ERROR
    if (is_array($field->value)) {
        return;
    } else {
        $decoded_value = json_decode($field->value, true);
    }

    if (!$decoded_value || !is_array($decoded_value)) {
        return;
    }

    $field->value = $decoded_value;
}
JamesNGarrett commented 1 year ago

I cannot replicate the error.

Could you provide exact instructions of how to generate the error on a clean install?

Amelie-Mahild commented 1 year ago

I just did a new installation of Joomla 4, updated it and followed these steps:

  1. Create new Categorie in: Components > Contacts > Categories Title: Test

  2. Create new Field Group in: Components > Contacts > Field Groups (Mail) Title: TestGroup Permissions: Edit Custom Field Value: Allowed

  3. Create new Fields in: Components > Contacts > Fields (Mail)

Two Fields of type text: Title: TestSub1/TestSub2 FieldGroup: TestGroup Only Use in Subform: Yes

One Field of type subform: Title: Testsubform FieldGroup: TestGroup Category: Test Repeatable: Yes Fields: TestSub1 + TestSub2

(I only edited the described fields.. everything else as default)

  1. Create new Contact in: Components > Contacts > Contacts Title: Test Email: xxx Category: Test

  2. Assign Home Menu Item to Single Contact...

  3. Test Form

  4. json-decode

Tested both with PHP 8.0 and PHP 8.1

JamesNGarrett commented 1 year ago

Apologies. I didn't note the significance of the "(Mail)" in the original issue. I can replicate the error.

The PlgFieldsSubform->onCustomFieldsBeforePrepareField() assumes that the subform data will be coming from the database as json, whereas the data (for mail custom fields) is coming from direct from the input passed to the FieldHelpers $valuesToOverride param as an array.

Your fix seems like the most straightforward solution. Could you raise a PR or would you like someone else to do it?

    public function onCustomFieldsBeforePrepareField($context, $item, $field)
    {
        if (!$this->isTypeSupported($field->type)) {
            return;
        }

        if (is_array($field->value)){
            return;
        }

        $decoded_value = json_decode($field->value, true);

        if (!$decoded_value || !is_array($decoded_value)) {
            return;
        }

        $field->value = $decoded_value;
    }
Amelie-Mahild commented 1 year ago

Cool. I´m new to GitHub and would be happy if someone could raise the PR for me. Thank you :)

richard67 commented 1 year ago

Closing as having a pull request. Please test #39842 . Thanks in advance.