Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/Db/Column.php
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ class Column extends EntitySuper implements JsonSerializable {
protected ?string $lastEditByDisplayName = null;
protected ?ViewColumnInformation $viewColumnInformation = null;

protected const VIRTUAL_PROPERTIES = ['createdByDisplayName', 'lastEditByDisplayName', 'viewColumnInformation'];
protected const VIRTUAL_PROPERTIES = ['createdByDisplayName', 'lastEditByDisplayName', 'viewColumnInformation', 'columnName'];

public function __construct() {
$this->addType('id', 'integer');
Expand Down
43 changes: 41 additions & 2 deletions lib/Db/Row2.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class Row2 implements JsonSerializable {
private ?string $lastEditBy = null;
private ?string $lastEditAt = null;
private ?array $data = [];
private array $cellMetadata = [];
private array $changedColumnIds = []; // collect column ids that have changed after $loaded = true

private bool $loaded = false; // set to true if model is loaded, after that changed column ids will be collected
Expand Down Expand Up @@ -134,17 +135,44 @@ public function filterDataByColumns(array $columns): array {
}

/**
* @psalm-return TablesRow
* add response-only metadata for a specific column
*/
public function addCellMeta(int $columnId, array $meta): void {
if (!isset($this->cellMetadata[$columnId])) {
$this->cellMetadata[$columnId] = [];
}
$this->cellMetadata[$columnId] = array_merge($this->cellMetadata[$columnId], $meta);
}

/**
* @return array{
* id: int|null,
* tableId: int|null,
* createdBy: string|null,
* createdAt: string|null,
* lastEditBy: string|null,
* lastEditAt: string|null,
* data: list<array<array-key, mixed>>
* }
*/
public function jsonSerialize(): array {
$data = [];
foreach ($this->data as $cell) {
$colId = $cell['columnId'];
$merged = $cell;
if (isset($this->cellMetadata[$colId])) {
$merged = array_merge($merged, $this->cellMetadata[$colId]);
}
$data[] = $merged;
}
return [
'id' => $this->id,
'tableId' => $this->tableId,
'createdBy' => $this->createdBy,
'createdAt' => $this->createdAt,
'lastEditBy' => $this->lastEditBy,
'lastEditAt' => $this->lastEditAt,
'data' => $this->data,
'data' => $data,
];
}

Expand Down Expand Up @@ -191,4 +219,15 @@ public function markAsLoaded(): void {
$this->loaded = true;
}

/**
* attach columnName as metadata for each cell
*/
public function addColumnNames(array $fullRowData): void {
foreach ($fullRowData as $meta) {
if (isset($meta['columnId']) && array_key_exists('columnName', $meta)) {
$this->addCellMeta((int)$meta['columnId'], ['columnName' => $meta['columnName']]);
}
}
}

}
2 changes: 1 addition & 1 deletion lib/ResponseDefinitions.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@
* createdAt: string,
* lastEditBy: string,
* lastEditAt: string,
* data: ?array{columnId: int, value: mixed},
* data: ?array{columnId: int, columnName: string, value: mixed},
* }
*
* @psalm-type TablesShare = array{
Expand Down
26 changes: 25 additions & 1 deletion lib/Service/RowService.php
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,28 @@ public function create(?int $tableId, ?int $viewId, RowDataInput|array $data): R
throw new InternalError('Cannot create row without table or view in context');
}

$fullRowData = [];
$columnNames = [];

foreach ($columns as $column) {
$columnNames[$column->getId()] = $column->getTitle();
}

$rows = $data instanceof RowDataInput ? iterator_to_array($data) : $data;

foreach ($rows as $row) {
$colId = (int)$row['columnId'];
if (!isset($columnNames[$colId])) {
continue;
}

$fullRowData[] = [
'columnId' => $colId,
'value' => $row['value'],
'columnName' => $columnNames[$colId],
];
}

$tableId = $tableId ?? $view->getTableId();

$data = $data instanceof RowDataInput ? $data : RowDataInput::fromArray($data);
Expand All @@ -220,6 +242,8 @@ public function create(?int $tableId, ?int $viewId, RowDataInput|array $data): R
$row2->setData($data);
try {
$insertedRow = $this->row2Mapper->insert($row2);
// attach columnName to returned row for the response only
$insertedRow->addColumnNames($fullRowData);

$this->eventDispatcher->dispatchTyped(new RowAddedEvent($insertedRow));
$this->activityManager->triggerEvent(
Expand Down Expand Up @@ -334,7 +358,7 @@ private function cleanupAndValidateData(RowDataInput $data, array $columns, ?int
if (!$column && $viewId) {
throw new InternalError('Column with id ' . $entry['columnId'] . ' is not part of view with id ' . $viewId);
} elseif (!$column && $tableId) {
throw new InternalError('Column with id ' . $entry['columnId'] . ' is not part of table with id ' . $tableId);
throw new BadRequestError('Column with id ' . $entry['columnId'] . ' is not part of table with id ' . $tableId);
}

if (!$column) {
Expand Down
2 changes: 1 addition & 1 deletion phpunit.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
- SPDX-FileCopyrightText: 2021 Florian Steffens
- SPDX-License-Identifier: AGPL-3.0-or-later
-->
<phpunit bootstrap="tests/bootstrap.php" colors="true">
<phpunit bootstrap="tests/Unit/bootstrap.php" colors="true">
<testsuites>
<testsuite name="unit">
<directory>./tests/Unit</directory>
Expand Down
33 changes: 33 additions & 0 deletions tests/unit/Db/Row2Test.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

declare(strict_types=1);

/**
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OCA\Tables\Tests\Unit\Db;

use OCA\Tables\Db\Row2;
use PHPUnit\Framework\TestCase;

class Row2Test extends TestCase {
public function testJsonSerializeMergesCellMetadata(): void {
$row = new Row2();
$row->setTableId(1);

$row->setData([
['columnId' => 57, 'value' => 'foo'],
['columnId' => 58, 'value' => 'bar'],
]);

$json = $row->jsonSerialize();
$this->assertArrayNotHasKey('columnName', $json['data'][0]);

$row->addCellMeta(57, ['columnName' => 'Title 57']);
$resp = $row->jsonSerialize();
$this->assertArrayHasKey('columnName', $resp['data'][0]);
$this->assertSame('Title 57', $resp['data'][0]['columnName']);
}
}
Loading