Project

General

Profile

Actions

Bug #105004

closed

PHP Warning: Array to string conversion when persisting JSON data (persists "Array" if warnings are silenced)

Added by Benjamin Franzke about 1 month ago. Updated 5 days ago.

Status:
Closed
Priority:
Should have
Assignee:
Category:
WebHooks - Incoming = Reactions + Outgoing
Target version:
Start date:
2024-09-17
Due date:
% Done:

100%

Estimated time:
TYPO3 Version:
13
PHP Version:
Tags:
Complexity:
Is Regression:
Sprint Focus:

Description

Version: 13.3.0

Steps to reproduce:

composer create-project typo3/cms-base-distribution project-name ^13
Install via vendor/bin/typo3 setup
Database: sqlite
Module: Webhooks > Create new record
Select trigger "typo3/file-added"
Add name: foobar,
URL: http://127.0.0.1/
Secret: press dice-button

Press Save

Exception/Warning:

PHP Warning: Array to string conversion in […]/vendor/doctrine/dbal/src/Driver/PDO/Statement.php line 26

(1/1) #1476107295 TYPO3\CMS\Core\Error\Exception
PHP Warning: Array to string conversion in /home/ben/src/test-13-3/vendor/doctrine/dbal/src/Driver/PDO/Statement.php line 26

in /home/ben/src/test-13-3/vendor/typo3/cms-core/Classes/Error/ErrorHandler.php line 138
        }

        $message = self::ERROR_LEVEL_LABELS[$errorLevel] . ': ' . $errorMessage . ' in ' . $errorFile . ' line ' . $errorLine;
        if ($errorLevel & $this->exceptionalErrors) {
            throw new Exception($message, 1476107295);
        }

        $message = $this->getFormattedLogMessage($message);

at TYPO3\CMS\Core\Error\ErrorHandler->handleError()
at PDOStatement->bindValue()
in /home/ben/src/test-13-3/vendor/doctrine/dbal/src/Driver/PDO/Statement.php line 26
    {
        $pdoType = $this->convertParamType($type);

        try {
            $this->stmt->bindValue($param, $value, $pdoType);
        } catch (PDOException $exception) {
            throw Exception::new($exception);
        }
    }
at Doctrine\DBAL\Driver\PDO\Statement->bindValue()
in /home/ben/src/test-13-3/vendor/doctrine/dbal/src/Driver/Middleware/AbstractStatementMiddleware.php line 19
    }

    public function bindValue(int|string $param, mixed $value, ParameterType $type): void
    {
        $this->wrappedStatement->bindValue($param, $value, $type);
    }

    public function execute(): Result
    {
at Doctrine\DBAL\Driver\Middleware\AbstractStatementMiddleware->bindValue()
in /home/ben/src/test-13-3/vendor/doctrine/dbal/src/Connection.php line 1243
                } else {
                    $bindingType = ParameterType::STRING;
                }

                $stmt->bindValue($bindIndex, $value, $bindingType);

                ++$bindIndex;
            }
        } else {
at Doctrine\DBAL\Connection->bindParameters()
in /home/ben/src/test-13-3/vendor/doctrine/dbal/src/Connection.php line 865
                [$sql, $params, $types] = $this->expandArrayParameters($sql, $params, $types);

                $stmt = $connection->prepare($sql);

                $this->bindParameters($stmt, $params, $types);

                return $stmt->execute()
                    ->rowCount();
            }
at Doctrine\DBAL\Connection->executeStatement()
in /home/ben/src/test-13-3/vendor/doctrine/dbal/src/Connection.php line 510
            $values[]  = $value;
            $set[]     = '?';
        }

        return $this->executeStatement(
            'INSERT INTO ' . $table . ' (' . implode(', ', $columns) . ')' .
            ' VALUES (' . implode(', ', $set) . ')',
            $values,
            is_string(key($types)) ? $this->extractTypeValues($columns, $types) : $types,
at Doctrine\DBAL\Connection->insert()
in /home/ben/src/test-13-3/vendor/typo3/cms-core/Classes/Database/Connection.php line 192
     */
    public function insert(string $tableName, array $data, array $types = []): int
    {
        $this->ensureDatabaseValueTypes($tableName, $data, $types);
        return parent::insert(
            $this->quoteIdentifier($tableName),
            $this->quoteColumnValuePairs($data),
            $this->quoteColumnTypes($types)
        );
at TYPO3\CMS\Core\Database\Connection->insert()
in /home/ben/src/test-13-3/vendor/typo3/cms-core/Classes/DataHandling/DataHandler.php line 7721
            $connection = $this->connectionPool->getConnectionForTable($table);
            $insertErrorMessage = '';
            try {
                // Execute the INSERT query:
                $connection->insert($table, $fieldArray);
            } catch (DBALException $e) {
                $insertErrorMessage = $e->getPrevious()->getMessage();
            }
            // If succees, do...:
at TYPO3\CMS\Core\DataHandling\DataHandler->insertDB()
in /home/ben/src/test-13-3/vendor/typo3/cms-core/Classes/DataHandling/DataHandler.php line 1080
                            $this->insertDB($table, $id, $fieldArray, true, (int)($incomingFieldArray['uid'] ?? 0));
                            // Hold auto-versionized ids of placeholders
                            $this->autoVersionIdMap[$table][$this->substNEWwithIDs[$id]] = $this->substNEWwithIDs[$id];
                        } else {
                            $this->insertDB($table, $id, $fieldArray, false, (int)($incomingFieldArray['uid'] ?? 0));
                        }
                    } else {
                        if ($table === 'pages') {
                            // Only a certain number of fields needs to be checked for updates,
at TYPO3\CMS\Core\DataHandling\DataHandler->process_datamap()
in /home/ben/src/test-13-3/vendor/typo3/cms-backend/Classes/Controller/EditDocumentController.php line 554
        }

        // Perform the saving operation with DataHandler:
        if ($this->doSave === true) {
            $tce->process_datamap();
            $tce->process_cmdmap();

            // Update the module menu for the current backend user, as they updated their UI language
            $currentUserId = $beUser->getUserId();

Files


Related issues 1 (0 open1 closed)

Related to TYPO3 Core - Task #105208: Ensure correct type resolving in `AbstractSchemaManager`ClosedStefan Bürk2024-10-05

Actions
Actions #1

Updated by Benjamin Franzke about 1 month ago

  • Description updated (diff)
Actions #2

Updated by Benjamin Franzke about 1 month ago

Note that sqlite schema differs between v12 and v13:

v12:

.schema sys_webhook 
CREATE TABLE sys_webhook (
  "uid" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
  "pid" INTEGER UNSIGNED DEFAULT 0 NOT NULL,
  "updatedon" INTEGER UNSIGNED DEFAULT 0 NOT NULL,
  "createdon" INTEGER UNSIGNED DEFAULT 0 NOT NULL,
  "deleted" SMALLINT UNSIGNED DEFAULT 0 NOT NULL,
  "disabled" SMALLINT UNSIGNED DEFAULT 0 NOT NULL,
  "starttime" INTEGER UNSIGNED DEFAULT 0 NOT NULL,
  "endtime" INTEGER UNSIGNED DEFAULT 0 NOT NULL,
  "description" CLOB DEFAULT NULL,
  "name" VARCHAR(100) DEFAULT '' NOT NULL,
  "url" VARCHAR(2048) DEFAULT '' NOT NULL,
  "method" VARCHAR(10) DEFAULT '' NOT NULL,
  "secret" VARCHAR(255) DEFAULT '' NOT NULL,
  "webhook_type" VARCHAR(255) DEFAULT '' NOT NULL,
  "verify_ssl" INTEGER DEFAULT 1 NOT NULL,
  "additional_headers" CLOB DEFAULT NULL --(DC2Type:json),
  "identifier" VARCHAR(36) DEFAULT '' NOT NULL
)

v13:

.schema sys_webhook 
CREATE TABLE IF NOT EXISTS "sys_webhook" (
  "uid" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
  "pid" INTEGER UNSIGNED DEFAULT 0 NOT NULL,
  "updatedon" INTEGER UNSIGNED DEFAULT 0 NOT NULL,
  "createdon" INTEGER UNSIGNED DEFAULT 0 NOT NULL,
  "deleted" SMALLINT UNSIGNED DEFAULT 0 NOT NULL,
  "disabled" SMALLINT UNSIGNED DEFAULT 0 NOT NULL,
  "starttime" INTEGER UNSIGNED DEFAULT 0 NOT NULL,
  "endtime" INTEGER UNSIGNED DEFAULT 0 NOT NULL,
  "description" CLOB DEFAULT NULL COLLATE "BINARY",
  "webhook_type" VARCHAR(255) DEFAULT '' NOT NULL COLLATE "BINARY",
  "name" VARCHAR(100) DEFAULT '' NOT NULL COLLATE "BINARY",
  "identifier" VARCHAR(36) DEFAULT '' NOT NULL COLLATE "BINARY",
  "secret" VARCHAR DEFAULT '' NOT NULL COLLATE "BINARY",
  "url" CLOB DEFAULT '' NOT NULL COLLATE "BINARY",
  "method" VARCHAR(10) DEFAULT '' NOT NULL COLLATE "BINARY",
  "verify_ssl" SMALLINT UNSIGNED DEFAULT 1 NOT NULL,
  "additional_headers" CLOB DEFAULT NULL COLLATE "BINARY" 
);

While v12 has "additional_headers" CLOB DEFAULT NULL --(DC2Type:json), it is just "additional_headers" CLOB DEFAULT NULL COLLATE "BINARY" in v13.

That means: Introspection that uses connection->createSchemaManager()->introspectSchema to obtain target types will detect the column as a string-type and thus won't json_encode array`s to strings before sending binding them via bindValue()

Actions #3

Updated by Benjamin Franzke about 1 month ago

  • Subject changed from PHP Warning: Array to string conversion in /home/ben/src/test-13-3/vendor/doctrine/dbal/src/Driver/PDO/Statement.php line 26 to PHP Warning: Array to string conversion when persisting JSON data (persists "Array" if warnings are silenced)
Actions #4

Updated by Benjamin Franzke about 1 month ago

I guess this happended because doctrine removed type comments in doctrine/dbal 4.0:
https://github.com/doctrine/dbal/pull/5107

See also: https://github.com/doctrine/dbal/blob/4.1.x/UPGRADE.md#bc-break-deployed-database-schema-no-longer-contains-the-information-about-abstract-data-types

That means: We must not longer introspect the schema to obtain target types – we should rather use our own schema.

Actions #5

Updated by Benjamin Franzke about 1 month ago

  • Description updated (diff)
Actions #6

Updated by Stefan Bürk about 1 month ago

  • Assignee set to Stefan Bürk
Actions #7

Updated by Stefan Bürk 15 days ago

  • Related to Task #105208: Ensure correct type resolving in `AbstractSchemaManager` added
Actions #8

Updated by Gerrit Code Review 15 days ago

  • Status changed from New to Under Review

Patch set 1 for branch main of project Packages/TYPO3.CMS has been pushed to the review server.
It is available at https://review.typo3.org/c/Packages/TYPO3.CMS/+/86436

Actions #9

Updated by Gerrit Code Review 15 days ago

Patch set 2 for branch main of project Packages/TYPO3.CMS has been pushed to the review server.
It is available at https://review.typo3.org/c/Packages/TYPO3.CMS/+/86436

Actions #10

Updated by Gerrit Code Review 14 days ago

Patch set 3 for branch main of project Packages/TYPO3.CMS has been pushed to the review server.
It is available at https://review.typo3.org/c/Packages/TYPO3.CMS/+/86436

Actions #11

Updated by Gerrit Code Review 14 days ago

Patch set 4 for branch main of project Packages/TYPO3.CMS has been pushed to the review server.
It is available at https://review.typo3.org/c/Packages/TYPO3.CMS/+/86436

Actions #12

Updated by Gerrit Code Review 13 days ago

Patch set 5 for branch main of project Packages/TYPO3.CMS has been pushed to the review server.
It is available at https://review.typo3.org/c/Packages/TYPO3.CMS/+/86436

Actions #13

Updated by Gerrit Code Review 10 days ago

Patch set 6 for branch main of project Packages/TYPO3.CMS has been pushed to the review server.
It is available at https://review.typo3.org/c/Packages/TYPO3.CMS/+/86436

Actions #14

Updated by Gerrit Code Review 9 days ago

Patch set 7 for branch main of project Packages/TYPO3.CMS has been pushed to the review server.
It is available at https://review.typo3.org/c/Packages/TYPO3.CMS/+/86436

Actions #15

Updated by Gerrit Code Review 9 days ago

Patch set 8 for branch main of project Packages/TYPO3.CMS has been pushed to the review server.
It is available at https://review.typo3.org/c/Packages/TYPO3.CMS/+/86436

Actions #16

Updated by Gerrit Code Review 9 days ago

Patch set 9 for branch main of project Packages/TYPO3.CMS has been pushed to the review server.
It is available at https://review.typo3.org/c/Packages/TYPO3.CMS/+/86436

Actions #17

Updated by Gerrit Code Review 9 days ago

Patch set 10 for branch main of project Packages/TYPO3.CMS has been pushed to the review server.
It is available at https://review.typo3.org/c/Packages/TYPO3.CMS/+/86436

Actions #18

Updated by Stefan Bürk 9 days ago

  • Status changed from Under Review to Resolved
  • % Done changed from 0 to 100
Actions #19

Updated by Benni Mack 5 days ago

  • Status changed from Resolved to Closed
Actions

Also available in: Atom PDF