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
6 changes: 5 additions & 1 deletion src/Migration/Destination.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,16 @@ public function setSource(Source $source): self
*
* @param array<string> $resources Resources to transfer
* @param callable(array<Resource>): void $callback to run after transfer
* @param string $rootResourceId Root resource ID, If enabled you can only transfer a single root resource
* @param string $rootResourceId Root resource ID. If set, only this root resource is transferred.
* @param string $rootResourceType Resource type for $rootResourceId.
* @param string $rootResourceChildId Optional child filter under the root resource. For database roots, this is the collection/table ID.
*/
public function run(
array $resources,
callable $callback,
string $rootResourceId = '',
string $rootResourceType = '',
string $rootResourceChildId = '',
): void {
$this->source->run(
$resources,
Expand All @@ -41,6 +44,7 @@ function (array $resources) use ($callback) {
},
$rootResourceId,
$rootResourceType,
$rootResourceChildId,
);
}

Expand Down
13 changes: 8 additions & 5 deletions src/Migration/Destinations/CSV.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
class CSV extends Destination
{
protected Device $deviceForFiles;
protected string $resourceId;
protected string $databaseId;
protected string $tableId;
protected string $directory;
protected string $outputFile;
protected Local $local;
Expand All @@ -32,7 +33,8 @@ class CSV extends Destination
*/
public function __construct(
Device $deviceForFiles,
string $resourceId,
string $databaseId,
string $tableId,
string $directory,
string $filename,
array $allowedColumns = [],
Expand All @@ -42,7 +44,8 @@ public function __construct(
private readonly bool $includeHeaders = true,
) {
$this->deviceForFiles = $deviceForFiles;
$this->resourceId = $resourceId;
$this->databaseId = $databaseId;
$this->tableId = $tableId;
$this->directory = $directory;
$this->outputFile = $this->sanitizeFilename($filename);
$this->local = new Local(\sys_get_temp_dir() . '/csv_export_' . uniqid());
Expand Down Expand Up @@ -168,7 +171,7 @@ public function shutdown(): void
$destPath = $this->deviceForFiles->getPath($this->directory . '/' . $filename);

if (!$this->local->exists($sourcePath)) {
throw new \Exception("No data to export for resource: $this->resourceId", MigrationException::CODE_NOT_FOUND);
throw new \Exception("No data to export for table {$this->tableId} in database {$this->databaseId}", MigrationException::CODE_NOT_FOUND);
}

try {
Expand All @@ -193,7 +196,7 @@ public function shutdown(): void
UtopiaResource::TYPE_ROW,
Transfer::GROUP_DATABASES,
'Error cleaning up: ' . $this->local->getRoot(),
$this->resourceId
$this->tableId
));
}
}
Expand Down
13 changes: 8 additions & 5 deletions src/Migration/Destinations/JSON.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
class JSON extends Destination
{
protected Device $deviceForFiles;
protected string $resourceId;
protected string $databaseId;
protected string $tableId;
protected string $directory;
protected string $outputFile;
protected Local $local;
Expand All @@ -36,13 +37,15 @@ class JSON extends Destination
*/
public function __construct(
Device $deviceForFiles,
string $resourceId,
string $databaseId,
string $tableId,
string $directory,
string $filename,
array $allowedColumns = [],
) {
$this->deviceForFiles = $deviceForFiles;
$this->resourceId = $resourceId;
$this->databaseId = $databaseId;
$this->tableId = $tableId;
$this->directory = $directory;
$this->outputFile = $this->sanitizeFilename($filename);

Expand Down Expand Up @@ -178,7 +181,7 @@ public function shutdown(): void
$destPath = $this->deviceForFiles->getPath($this->directory . '/' . $filename);

if (!$this->local->exists($sourcePath)) {
throw new Exception("No data to export for resource: $this->resourceId");
throw new Exception("No data to export for table {$this->tableId} in database {$this->databaseId}");
}

$handle = null;
Expand Down Expand Up @@ -217,7 +220,7 @@ public function shutdown(): void
UtopiaResource::TYPE_ROW,
Transfer::GROUP_DATABASES,
'Error cleaning up: ' . $this->local->getRoot(),
$this->resourceId
$this->tableId
));
}
}
Expand Down
7 changes: 5 additions & 2 deletions src/Migration/Source.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,15 @@ public function callback(array $resources): void
*
* @param array<string> $resources Resources to transfer
* @param callable $callback Callback to run after transfer
* @param string $rootResourceId Root resource ID, If enabled you can only transfer a single root resource
* @param string $rootResourceId Root resource ID. If set, only this root resource is transferred.
* @param string $rootResourceType Resource type for $rootResourceId. Required when $rootResourceId is set.
* @param string $rootResourceChildId Optional child filter under the root resource. For database roots, this is the collection/table ID.
*/
public function run(array $resources, callable $callback, string $rootResourceId = '', string $rootResourceType = ''): void
public function run(array $resources, callable $callback, string $rootResourceId = '', string $rootResourceType = '', string $rootResourceChildId = ''): void
{
$this->rootResourceId = $rootResourceId;
$this->rootResourceType = $rootResourceType;
$this->rootResourceChildId = $rootResourceChildId;

$this->transferCallback = function (array $returnedResources) use ($callback, $resources) {
$prunedResources = [];
Expand Down
31 changes: 8 additions & 23 deletions src/Migration/Sources/Appwrite.php
Original file line number Diff line number Diff line change
Expand Up @@ -830,17 +830,7 @@ private function exportDatabases(int $batchSize, array $resources = []): void
$queries = [$this->reader->queryLimit($batchSize)];

if ($this->rootResourceId !== '' && ($this->rootResourceType === Resource::TYPE_DATABASE || $this->rootResourceType === Resource::TYPE_DATABASE_DOCUMENTSDB)) {
$targetDatabaseId = $this->rootResourceId;

// Handle database:collection format - extract database ID
if (\str_contains($this->rootResourceId, ':')) {
$parts = \explode(':', $this->rootResourceId, 2);
if (\count($parts) === 2) {
$targetDatabaseId = $parts[0];
}
}

$queries[] = $this->reader->queryEqual('$id', [$targetDatabaseId]);
$queries[] = $this->reader->queryEqual('$id', [$this->rootResourceId]);
$queries[] = $this->reader->queryLimit(1);
}

Expand Down Expand Up @@ -904,24 +894,19 @@ private function exportEntities(string $databaseName, int $batchSize): void
$queries = [$this->reader->queryLimit($batchSize)];
$tables = [];

// Filter to specific table if rootResourceType is database with database:collection format
// Filter to a specific table when the root is a database with a child set, or
// when the root itself is a table.
if (
$this->rootResourceId !== '' &&
$this->rootResourceType === Resource::TYPE_DATABASE &&
\str_contains($this->rootResourceId, ':')
$this->rootResourceChildId !== '' &&
$this->rootResourceType === Resource::TYPE_DATABASE
) {
$parts = \explode(':', $this->rootResourceId, 2);
if (\count($parts) === 2) {
$targetTableId = $parts[1]; // table ID
$queries[] = $this->reader->queryEqual('$id', [$targetTableId]);
$queries[] = $this->reader->queryLimit(1);
}
$queries[] = $this->reader->queryEqual('$id', [$this->rootResourceChildId]);
$queries[] = $this->reader->queryLimit(1);
} elseif (
$this->rootResourceId !== '' &&
$this->rootResourceType === Resource::TYPE_TABLE
) {
$targetTableId = $this->rootResourceId;
$queries[] = $this->reader->queryEqual('$id', [$targetTableId]);
$queries[] = $this->reader->queryEqual('$id', [$this->rootResourceId]);
$queries[] = $this->reader->queryLimit(1);
} elseif ($lastTable) {
$queries[] = $this->reader->queryCursorAfter($lastTable);
Expand Down
23 changes: 11 additions & 12 deletions src/Migration/Sources/CSV.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,9 @@ class CSV extends Source

private string $filePath;

/**
* format: `{databaseId:tableId}`
*/
private string $resourceId;
private string $databaseId;

private string $tableId;

private Device $device;

Expand All @@ -39,15 +38,17 @@ class CSV extends Source
private bool $downloaded = false;

public function __construct(
string $resourceId,
string $databaseId,
string $tableId,
string $filePath,
Device $device,
?UtopiaDatabase $dbForProject,
?callable $getDatabasesDB = null,
) {
$this->device = $device;
$this->filePath = $filePath;
$this->resourceId = $resourceId;
$this->databaseId = $databaseId;
$this->tableId = $tableId;
$this->database = new DatabaseReader($dbForProject, $getDatabasesDB);
}

Expand Down Expand Up @@ -131,10 +132,8 @@ private function exportRows(int $batchSize): void
$columns = [];
$lastColumn = null;

[$databaseId, $tableId] = \explode(':', $this->resourceId);

$databases = $this->database->listDatabases([
$this->database->queryEqual('$id', [$databaseId]),
$this->database->queryEqual('$id', [$this->databaseId]),
$this->database->queryLimit(1),
]);

Expand All @@ -157,8 +156,8 @@ private function exportRows(int $batchSize): void
];

$tablePayload = [
'id' => $tableId,
'name' => $tableId,
'id' => $this->tableId,
'name' => $this->tableId,
'documentSecurity' => false,
'rowSecurity' => false,
'permissions' => [],
Expand Down Expand Up @@ -504,7 +503,7 @@ private function validateCSVHeaders(array $headers, array $columnTypes, array $r
UtopiaResource::TYPE_ROW,
Transfer::GROUP_DATABASES,
\implode(', ', $messages),
$this->resourceId
$this->tableId
));
}
}
Expand Down
18 changes: 9 additions & 9 deletions src/Migration/Sources/JSON.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,9 @@ class JSON extends Source
{
private string $filePath;

/**
* format: `{databaseId:tableId}`
*/
private string $resourceId;
private string $databaseId;

private string $tableId;

private Device $device;

Expand All @@ -35,14 +34,16 @@ class JSON extends Source
private bool $downloaded = false;

public function __construct(
string $resourceId,
string $databaseId,
string $tableId,
string $filePath,
Device $device,
?UtopiaDatabase $dbForProject
) {
$this->device = $device;
$this->filePath = $filePath;
$this->resourceId = $resourceId;
$this->databaseId = $databaseId;
$this->tableId = $tableId;

/* kept for composer check */
$this->dbForProject = $dbForProject;
Expand Down Expand Up @@ -120,9 +121,8 @@ protected function exportGroupDatabases(int $batchSize, array $resources): void
*/
private function exportRows(int $batchSize): void
{
[$databaseId, $tableId] = \explode(':', $this->resourceId);
$database = new Database($databaseId, '');
$table = new Table($database, '', $tableId);
$database = new Database($this->databaseId, '');
$table = new Table($database, '', $this->tableId);

$this->withJsonItems(function ($items) use ($table, $batchSize) {
$buffer = [];
Expand Down
7 changes: 5 additions & 2 deletions src/Migration/Target.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ abstract class Target

protected string $rootResourceId = '';

protected string $rootResourceChildId = '';

protected string $rootResourceType = '';

abstract public static function getName(): string;
Expand All @@ -49,9 +51,10 @@ public function registerCache(Cache &$cache): void
*
* @param array<string> $resources Resources to transfer
* @param callable $callback Callback to run after transfer
* @param string $rootResourceId Root resource ID, If enabled you can only transfer a single root resource
* @param string $rootResourceId Root resource ID. If set, only this root resource is transferred.
* @param string $rootResourceChildId Optional child filter under the root resource. For database roots, this is the collection/table ID.
*/
abstract public function run(array $resources, callable $callback, string $rootResourceId = ''): void;
abstract public function run(array $resources, callable $callback, string $rootResourceId = '', string $rootResourceChildId = ''): void;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Abstract run signature is missing $rootResourceType

The abstract declares the 4th positional parameter as $rootResourceChildId, but both concrete overrides (Source::run and Destination::run) insert $rootResourceType as the 4th parameter and push $rootResourceChildId to 5th. Any caller typed as Target that passes 4 positional args will silently route their $rootResourceChildId value into $rootResourceType, leaving $rootResourceChildId as '' and making table-scoped transfers silently no-ops.

Suggested change
abstract public function run(array $resources, callable $callback, string $rootResourceId = '', string $rootResourceChildId = ''): void;
abstract public function run(array $resources, callable $callback, string $rootResourceId = '', string $rootResourceType = '', string $rootResourceChildId = ''): void;


/**
* Report Resources
Expand Down
7 changes: 6 additions & 1 deletion src/Migration/Transfer.php
Original file line number Diff line number Diff line change
Expand Up @@ -267,19 +267,23 @@ public function getStatusCounters(): array
*
* @param array<string> $resources Resources to transfer
* @param callable $callback Callback to run after transfer
* @param string|null $rootResourceId Root resource ID, If enabled you can only transfer a single root resource
* @param string|null $rootResourceId Root resource ID. If set, only this root resource is transferred.
* @param string|null $rootResourceType Resource type for $rootResourceId. Required when $rootResourceId is set.
* @param string|null $rootResourceChildId Optional child filter under the root resource. For database roots, this is the collection/table ID.
* @throws \Exception
*/
public function run(
array $resources,
callable $callback,
?string $rootResourceId = null,
?string $rootResourceType = null,
?string $rootResourceChildId = null,
): void {
// Allows you to push entire groups if you want.
$computedResources = [];
$rootResourceId = $rootResourceId ?? '';
$rootResourceType = $rootResourceType ?? '';
$rootResourceChildId = $rootResourceChildId ?? '';

foreach ($resources as $resource) {
if (is_array($resource)) {
Expand Down Expand Up @@ -320,6 +324,7 @@ public function run(
$callback,
$rootResourceId,
$rootResourceType,
$rootResourceChildId,
);
}

Expand Down
Loading
Loading