From ea9f63545f59a29feb9c23ed8e4df9bdf21a69f6 Mon Sep 17 00:00:00 2001
From: Bradley Schofield <ionicisere@gmail.com>
Date: Tue, 12 Sep 2023 10:45:50 +0100
Subject: [PATCH 1/7] Fix Storage Size Reports

---
 playground.php                     | 88 +++++++++++++++---------------
 src/Migration/Cache.php            |  4 +-
 src/Migration/Sources/Appwrite.php | 71 +++++++++++++++++++++---
 src/Migration/Target.php           |  9 ++-
 4 files changed, 116 insertions(+), 56 deletions(-)

diff --git a/playground.php b/playground.php
index 91129932..c8705b4b 100644
--- a/playground.php
+++ b/playground.php
@@ -29,34 +29,34 @@
     $_ENV['SOURCE_APPWRITE_TEST_KEY']
 );
 
-$firebase = json_decode($_ENV['FIREBASE_TEST_ACCOUNT'], true);
+// $firebase = json_decode($_ENV['FIREBASE_TEST_ACCOUNT'], true);
+
+// $sourceFirebase = new Firebase(
+//     $firebase,
+//     $firebase['project_id'] ?? '',
+// );
+
+// $sourceNHost = new NHost(
+//     $_ENV['NHOST_TEST_SUBDOMAIN'] ?? '',
+//     $_ENV['NHOST_TEST_REGION'] ?? '',
+//     $_ENV['NHOST_TEST_SECRET'] ?? '',
+//     $_ENV['NHOST_TEST_DATABASE'] ?? '',
+//     $_ENV['NHOST_TEST_USERNAME'] ?? '',
+//     $_ENV['NHOST_TEST_PASSWORD'] ?? '',
+// );
+
+// $sourceSupabase = new Supabase(
+//     $_ENV['SUPABASE_TEST_ENDPOINT'] ?? '',
+//     $_ENV['SUPABASE_TEST_KEY'] ?? '',
+//     $_ENV['SUPABASE_TEST_HOST'] ?? '',
+//     $_ENV['SUPABASE_TEST_DATABASE'] ?? '',
+//     $_ENV['SUPABASE_TEST_USERNAME'] ?? '',
+//     $_ENV['SUPABASE_TEST_PASSWORD'] ?? '',
+// );
 
-$sourceFirebase = new Firebase(
-    $firebase,
-    $firebase['project_id'] ?? '',
-);
-
-$sourceNHost = new NHost(
-    $_ENV['NHOST_TEST_SUBDOMAIN'] ?? '',
-    $_ENV['NHOST_TEST_REGION'] ?? '',
-    $_ENV['NHOST_TEST_SECRET'] ?? '',
-    $_ENV['NHOST_TEST_DATABASE'] ?? '',
-    $_ENV['NHOST_TEST_USERNAME'] ?? '',
-    $_ENV['NHOST_TEST_PASSWORD'] ?? '',
-);
-
-$sourceSupabase = new Supabase(
-    $_ENV['SUPABASE_TEST_ENDPOINT'] ?? '',
-    $_ENV['SUPABASE_TEST_KEY'] ?? '',
-    $_ENV['SUPABASE_TEST_HOST'] ?? '',
-    $_ENV['SUPABASE_TEST_DATABASE'] ?? '',
-    $_ENV['SUPABASE_TEST_USERNAME'] ?? '',
-    $_ENV['SUPABASE_TEST_PASSWORD'] ?? '',
-);
-
-/**
- * Initialise All Destination Adapters
- */
+// /**
+//  * Initialise All Destination Adapters
+//  */
 $destinationAppwrite = new AppwriteDestination(
     $_ENV['DESTINATION_APPWRITE_TEST_PROJECT'],
     $_ENV['DESTINATION_APPWRITE_TEST_ENDPOINT'],
@@ -65,27 +65,29 @@
 
 $destinationLocal = new Local(__DIR__.'/localBackup/');
 
+var_dump($sourceAppwrite->report());
+
 /**
  * Initialise Transfer Class
  */
-$transfer = new Transfer(
-    $sourceFirebase,
-    $destinationLocal
-);
-
-$sourceFirebase->report();
-
-// /**
-//  * Run Transfer
-//  */
-$transfer->run($sourceFirebase->getSupportedResources(),
-    function (array $resources) {
-    }
-);
+// $transfer = new Transfer(
+//     $sourceAppwrite,
+//     $destinationAppwrite
+// );
+
+// $sourceAppwrite->report();
+
+// // /**
+// //  * Run Transfer
+// //  */
+// $transfer->run($sourceAppwrite->getSupportedResources(),
+//     function (array $resources) {
+//     }
+// );
 
-$report = [];
+// $report = [];
 
-$cache = $transfer->getCache()->getAll();
+// $cache = $transfer->getCache()->getAll();
 
 // foreach ($cache as $type => $resources) {
 //     foreach ($resources as $resource) {
diff --git a/src/Migration/Cache.php b/src/Migration/Cache.php
index b25545da..d3307c09 100644
--- a/src/Migration/Cache.php
+++ b/src/Migration/Cache.php
@@ -37,8 +37,8 @@ public function add($resource)
             $resource->setInternalId(uniqid());
         }
 
-        if ($resource->getName() == Resource::TYPE_FILE || $resource->getName() == Resource::TYPE_FUNCTION) {
-            /** @var File|Func $resource */
+        if ($resource->getName() == Resource::TYPE_FILE || $resource->getName() == Resource::TYPE_DEPLOYMENT) {
+            /** @var File|Deployment $resource */
             $resource->setData(''); // Prevent Memory Leak
         }
 
diff --git a/src/Migration/Sources/Appwrite.php b/src/Migration/Sources/Appwrite.php
index bc4a9b0d..8e60b3e7 100644
--- a/src/Migration/Sources/Appwrite.php
+++ b/src/Migration/Sources/Appwrite.php
@@ -203,15 +203,39 @@ public function report(array $resources = []): array
             if (in_array(Resource::TYPE_FILE, $resources)) {
                 $report[Resource::TYPE_FILE] = 0;
                 $report['size'] = 0;
-                $buckets = $storageClient->listBuckets()['buckets'];
+                $buckets = [];
+                $lastBucket = null;
+
+                while (true) {
+                    $currentBuckets = $storageClient->listBuckets($lastBucket ? [Query::cursorAfter($lastBucket)] : [Query::limit(20)])['buckets'];
+                    $buckets = array_merge($buckets, $currentBuckets);
+                    $lastBucket = $buckets[count($buckets) - 1]['$id'];
+
+                    if (count($currentBuckets) < 20) {
+                        break;
+                    }
+                }
+
                 foreach ($buckets as $bucket) {
-                    $files = $storageClient->listFiles($bucket['$id']);
-                    $report[Resource::TYPE_FILE] += $files['total'];
-                    foreach ($files['files'] as $file) {
+                    $files = [];
+                    $lastFile = null;
+
+                    while (true) {
+                        $currentFiles = $storageClient->listFiles($bucket['$id'], $lastFile ? [Query::cursorAfter($lastFile)] : [Query::limit(20)])['files'];
+                        $files = array_merge($files, $currentFiles);
+                        $lastFile = $files[count($files) - 1]['$id'];
+    
+                        if (count($currentFiles) < 20) {
+                            break;
+                        }
+                    }
+
+                    $report[Resource::TYPE_FILE] += count($files);
+                    foreach ($files as $file) {
                         $report['size'] += $storageClient->getFile($bucket['$id'], $file['$id'])['sizeOriginal'];
                     }
                 }
-                $report['size'] = $report['size'] / 1024 / 1024; // MB
+                $report['size'] = $report['size'] / 1000 / 1000; // MB
             }
 
             // Functions
@@ -1080,12 +1104,43 @@ private function exportDeploymentData(Func $func, array $deployment)
         $end = Transfer::STORAGE_MAX_CHUNK_SIZE - 1;
 
         // Get the file size
-        $fileSize = $deployment['size'];
+        $responseHeaders = [];
+
+        $this->call(
+            'HEAD',
+            "/functions/{$func->getId()}/deployments/{$deployment['$id']}/download",
+            [],
+            [],
+            $responseHeaders
+        );
 
-        if ($end > $fileSize) {
-            $end = $fileSize - 1;
+        // Content-Length header was missing, file is less than max buffer size.
+        if (!key_exists('Content-Length', $responseHeaders)) {
+            $file = $this->call(
+                'GET',
+                "/functions/{$func->getId()}/deployments/{$deployment['$id']}/download",
+                [],
+                [],
+                $responseHeaders
+            );
+
+            $deployment = new Deployment(
+                $deployment['$id'],
+                $func,
+                strlen($file),
+                $deployment['entrypoint'],
+                $start,
+                $end,
+                $file,
+                $deployment['activate']
+            );
+            $deployment->setInternalId($deployment->getId());
+
+            return $this->callback([$deployment]);
         }
 
+        $fileSize = $responseHeaders['Content-Length'];
+
         $deployment = new Deployment(
             $deployment['$id'],
             $func,
diff --git a/src/Migration/Target.php b/src/Migration/Target.php
index 41047158..8149e522 100644
--- a/src/Migration/Target.php
+++ b/src/Migration/Target.php
@@ -68,11 +68,10 @@ abstract public function report(array $resources = []): array;
      *
      * @throws \Exception
      */
-    protected function call(string $method, string $path = '', array $headers = [], array $params = []): array|string
+    protected function call(string $method, string $path = '', array $headers = [], array $params = [], &$responseHeaders = []): array|string
     {
         $headers = array_merge($this->headers, $headers);
         $ch = curl_init((str_contains($path, 'http') ? $path.(($method == 'GET' && ! empty($params)) ? '?'.http_build_query($params) : '') : $this->endpoint.$path.(($method == 'GET' && ! empty($params)) ? '?'.http_build_query($params) : '')));
-        $responseHeaders = [];
         $responseStatus = -1;
         $responseType = '';
         $responseBody = '';
@@ -96,7 +95,11 @@ protected function call(string $method, string $path = '', array $headers = [],
             unset($headers[$i]);
         }
 
-        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
+        if ($method === 'HEAD') {
+            curl_setopt($ch, CURLOPT_NOBODY, true);
+        } else {
+            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
+        }
         curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
         curl_setopt($ch, CURLOPT_USERAGENT, php_uname('s').'-'.php_uname('r').':php-'.phpversion());
         curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

From 7da5208ec76282b12e3ea9f69b96e63fa86b26d2 Mon Sep 17 00:00:00 2001
From: Bradley Schofield <ionicisere@gmail.com>
Date: Wed, 13 Sep 2023 10:49:20 +0100
Subject: [PATCH 2/7] Function, User, Database Fixes

- Fixes Datetime in Database
- Fixes Labels and Preferences in Users
- Fixes invalid ->setData on functions instead of deployments
---
 composer.json                           |  8 ++-
 playground.php                          | 74 +++++++++++++------------
 src/Migration/Cache.php                 |  4 +-
 src/Migration/Destinations/Appwrite.php | 12 +++-
 src/Migration/Resources/Auth/User.php   | 22 ++++++++
 src/Migration/Sources/Appwrite.php      |  9 +++
 6 files changed, 88 insertions(+), 41 deletions(-)

diff --git a/composer.json b/composer.json
index 6d6faa16..dcca3d2c 100644
--- a/composer.json
+++ b/composer.json
@@ -26,10 +26,16 @@
         "lint": "./vendor/bin/pint --test",
         "format": "./vendor/bin/pint"
     },
+    "repositories": [
+        {
+            "type": "path",
+            "url": "/Users/bradleyschofield/Documents/GitHub/appwrite/app/sdks/server-php"
+        }
+    ],
     "require": {
         "php": "8.*",
         "utopia-php/cli": "0.*",
-        "appwrite/appwrite": "10.0.*"
+        "appwrite/appwrite": "*"
     },
     "require-dev": {
         "phpunit/phpunit": "9.*",
diff --git a/playground.php b/playground.php
index 91129932..8588ed93 100644
--- a/playground.php
+++ b/playground.php
@@ -8,6 +8,7 @@
 require_once __DIR__.'/vendor/autoload.php';
 
 use Dotenv\Dotenv;
+use Utopia\CLI\Console;
 use Utopia\Migration\Destinations\Appwrite as AppwriteDestination;
 use Utopia\Migration\Destinations\Local;
 use Utopia\Migration\Resource;
@@ -29,30 +30,30 @@
     $_ENV['SOURCE_APPWRITE_TEST_KEY']
 );
 
-$firebase = json_decode($_ENV['FIREBASE_TEST_ACCOUNT'], true);
-
-$sourceFirebase = new Firebase(
-    $firebase,
-    $firebase['project_id'] ?? '',
-);
-
-$sourceNHost = new NHost(
-    $_ENV['NHOST_TEST_SUBDOMAIN'] ?? '',
-    $_ENV['NHOST_TEST_REGION'] ?? '',
-    $_ENV['NHOST_TEST_SECRET'] ?? '',
-    $_ENV['NHOST_TEST_DATABASE'] ?? '',
-    $_ENV['NHOST_TEST_USERNAME'] ?? '',
-    $_ENV['NHOST_TEST_PASSWORD'] ?? '',
-);
-
-$sourceSupabase = new Supabase(
-    $_ENV['SUPABASE_TEST_ENDPOINT'] ?? '',
-    $_ENV['SUPABASE_TEST_KEY'] ?? '',
-    $_ENV['SUPABASE_TEST_HOST'] ?? '',
-    $_ENV['SUPABASE_TEST_DATABASE'] ?? '',
-    $_ENV['SUPABASE_TEST_USERNAME'] ?? '',
-    $_ENV['SUPABASE_TEST_PASSWORD'] ?? '',
-);
+// $firebase = json_decode($_ENV['FIREBASE_TEST_ACCOUNT'], true);
+
+// $sourceFirebase = new Firebase(
+//     $firebase,
+//     $firebase['project_id'] ?? '',
+// );
+
+// $sourceNHost = new NHost(
+//     $_ENV['NHOST_TEST_SUBDOMAIN'] ?? '',
+//     $_ENV['NHOST_TEST_REGION'] ?? '',
+//     $_ENV['NHOST_TEST_SECRET'] ?? '',
+//     $_ENV['NHOST_TEST_DATABASE'] ?? '',
+//     $_ENV['NHOST_TEST_USERNAME'] ?? '',
+//     $_ENV['NHOST_TEST_PASSWORD'] ?? '',
+// );
+
+// $sourceSupabase = new Supabase(
+//     $_ENV['SUPABASE_TEST_ENDPOINT'] ?? '',
+//     $_ENV['SUPABASE_TEST_KEY'] ?? '',
+//     $_ENV['SUPABASE_TEST_HOST'] ?? '',
+//     $_ENV['SUPABASE_TEST_DATABASE'] ?? '',
+//     $_ENV['SUPABASE_TEST_USERNAME'] ?? '',
+//     $_ENV['SUPABASE_TEST_PASSWORD'] ?? '',
+// );
 
 /**
  * Initialise All Destination Adapters
@@ -69,16 +70,14 @@
  * Initialise Transfer Class
  */
 $transfer = new Transfer(
-    $sourceFirebase,
-    $destinationLocal
+    $sourceAppwrite,
+    $destinationAppwrite
 );
 
-$sourceFirebase->report();
-
 // /**
 //  * Run Transfer
 //  */
-$transfer->run($sourceFirebase->getSupportedResources(),
+$transfer->run($sourceAppwrite->getSupportedResources(),
     function (array $resources) {
     }
 );
@@ -87,10 +86,13 @@ function (array $resources) {
 
 $cache = $transfer->getCache()->getAll();
 
-// foreach ($cache as $type => $resources) {
-//     foreach ($resources as $resource) {
-//         if ($resource->getStatus() !== Resource::STATUS_ERROR) {
-//             continue;
-//         }
-//     }
-// }
+foreach ($cache as $type => $resources) {
+    foreach ($resources as $resource) {
+        /** @var Resource $resource */
+        if ($resource->getStatus() !== Resource::STATUS_ERROR) {
+            continue;
+        }
+        
+        Console::error($resource->getName().' '.$resource->getInternalId().' '.$resource->getMessage());
+    }
+}
diff --git a/src/Migration/Cache.php b/src/Migration/Cache.php
index b25545da..d3307c09 100644
--- a/src/Migration/Cache.php
+++ b/src/Migration/Cache.php
@@ -37,8 +37,8 @@ public function add($resource)
             $resource->setInternalId(uniqid());
         }
 
-        if ($resource->getName() == Resource::TYPE_FILE || $resource->getName() == Resource::TYPE_FUNCTION) {
-            /** @var File|Func $resource */
+        if ($resource->getName() == Resource::TYPE_FILE || $resource->getName() == Resource::TYPE_DEPLOYMENT) {
+            /** @var File|Deployment $resource */
             $resource->setData(''); // Prevent Memory Leak
         }
 
diff --git a/src/Migration/Destinations/Appwrite.php b/src/Migration/Destinations/Appwrite.php
index 2c1db1cc..ccd9b8a4 100644
--- a/src/Migration/Destinations/Appwrite.php
+++ b/src/Migration/Destinations/Appwrite.php
@@ -529,8 +529,8 @@ public function importAuthResource(Resource $resource): Resource
                     /** @var User $resource */
                     if (in_array(User::TYPE_EMAIL, $resource->getTypes())) {
                         $this->importPasswordUser($resource);
-                    } elseif (in_array(User::TYPE_ANONYMOUS, $resource->getTypes()) || in_array(User::TYPE_OAUTH, $resource->getTypes())) {
-                        $resource->setStatus(Resource::STATUS_WARNING, 'Anonymous and OAuth users cannot be imported.');
+                    } elseif (in_array(User::TYPE_OAUTH, $resource->getTypes())) {
+                        $resource->setStatus(Resource::STATUS_WARNING, 'OAuth users cannot be imported.');
 
                         return $resource;
                     } else {
@@ -563,6 +563,14 @@ public function importAuthResource(Resource $resource): Resource
                         $userService->updateStatus($resource->getId(), ! $resource->getDisabled());
                     }
 
+                    if ($resource->getPreferences()) {
+                        $userService->updatePrefs($resource->getId(), $resource->getPreferences());
+                    }
+
+                    if ($resource->getLabels()) {
+                        $userService->updateLabels($resource->getId(), $resource->getLabels());
+                    }
+
                     break;
                 case Resource::TYPE_TEAM:
                     /** @var Team $resource */
diff --git a/src/Migration/Resources/Auth/User.php b/src/Migration/Resources/Auth/User.php
index 6eb816f8..73dfade9 100644
--- a/src/Migration/Resources/Auth/User.php
+++ b/src/Migration/Resources/Auth/User.php
@@ -27,6 +27,8 @@ class User extends Resource
 
     protected array $types = [self::TYPE_ANONYMOUS];
 
+    protected array $labels = [];
+
     protected string $oauthProvider = '';
 
     protected bool $emailVerified = false;
@@ -44,6 +46,7 @@ public function __construct(
         Hash $passwordHash = null,
         string $phone = '',
         array $types = [self::TYPE_ANONYMOUS],
+        array $labels = [],
         string $oauthProvider = '',
         bool $emailVerified = false,
         bool $phoneVerified = false,
@@ -56,6 +59,7 @@ public function __construct(
         $this->passwordHash = $passwordHash;
         $this->phone = $phone;
         $this->types = $types;
+        $this->labels = $labels;
         $this->oauthProvider = $oauthProvider;
         $this->emailVerified = $emailVerified;
         $this->phoneVerified = $phoneVerified;
@@ -161,6 +165,24 @@ public function setTypes(string $types): self
         return $this;
     }
 
+    /**
+     * Get Labels
+     */
+    public function getLabels(): array
+    {
+        return $this->labels;
+    }
+
+    /**
+     * Set Labels
+     */
+    public function setLabels(array $labels): self
+    {
+        $this->labels = $labels;
+
+        return $this;
+    }
+
     /**
      * Get OAuth Provider
      */
diff --git a/src/Migration/Sources/Appwrite.php b/src/Migration/Sources/Appwrite.php
index 89c00a1c..07e15f98 100644
--- a/src/Migration/Sources/Appwrite.php
+++ b/src/Migration/Sources/Appwrite.php
@@ -300,6 +300,7 @@ private function exportUsers(int $batchSize)
                     $user['password'] ? new Hash($user['password'], $user['hash']) : null,
                     $user['phone'],
                     $this->calculateTypes($user),
+                    $user['labels'] ?? [],
                     '',
                     $user['emailVerification'],
                     $user['phoneVerification'],
@@ -650,6 +651,14 @@ private function convertAttribute(array $value, Collection $collection): Attribu
                     $value['onDelete'],
                     $value['side']
                 );
+            case 'datetime':
+                return new DateTime(
+                    $value['key'],
+                    $collection,
+                    $value['required'],
+                    $value['array'],
+                    $value['default']
+                );
         }
 
         throw new \Exception('Unknown attribute type: '.$value['type']);

From 34bc4de4fe712990c45853bf9e7a663d832b9bfa Mon Sep 17 00:00:00 2001
From: Bradley Schofield <ionicisere@gmail.com>
Date: Wed, 13 Sep 2023 10:53:17 +0100
Subject: [PATCH 3/7] Update composer.json

---
 composer.json | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/composer.json b/composer.json
index dcca3d2c..e4cbb417 100644
--- a/composer.json
+++ b/composer.json
@@ -26,16 +26,10 @@
         "lint": "./vendor/bin/pint --test",
         "format": "./vendor/bin/pint"
     },
-    "repositories": [
-        {
-            "type": "path",
-            "url": "/Users/bradleyschofield/Documents/GitHub/appwrite/app/sdks/server-php"
-        }
-    ],
     "require": {
         "php": "8.*",
         "utopia-php/cli": "0.*",
-        "appwrite/appwrite": "*"
+        "appwrite/appwrite": "10.0.0"
     },
     "require-dev": {
         "phpunit/phpunit": "9.*",

From 1c31ebe4f22c74ff595aaa8f1a6ae3bbc2b7fef1 Mon Sep 17 00:00:00 2001
From: Bradley Schofield <ionicisere@gmail.com>
Date: Wed, 13 Sep 2023 10:53:37 +0100
Subject: [PATCH 4/7] Update composer.json

---
 composer.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/composer.json b/composer.json
index e4cbb417..6d6faa16 100644
--- a/composer.json
+++ b/composer.json
@@ -29,7 +29,7 @@
     "require": {
         "php": "8.*",
         "utopia-php/cli": "0.*",
-        "appwrite/appwrite": "10.0.0"
+        "appwrite/appwrite": "10.0.*"
     },
     "require-dev": {
         "phpunit/phpunit": "9.*",

From f098e451789c73502b94e646ea18685dd0670ddf Mon Sep 17 00:00:00 2001
From: Bradley Schofield <ionicisere@gmail.com>
Date: Wed, 13 Sep 2023 10:58:00 +0100
Subject: [PATCH 5/7] Run Linter

---
 playground.php          | 4 ++--
 src/Migration/Cache.php | 1 -
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/playground.php b/playground.php
index 8588ed93..33c77ed3 100644
--- a/playground.php
+++ b/playground.php
@@ -88,11 +88,11 @@ function (array $resources) {
 
 foreach ($cache as $type => $resources) {
     foreach ($resources as $resource) {
-        /** @var Resource $resource */
+        /** @var resource $resource */
         if ($resource->getStatus() !== Resource::STATUS_ERROR) {
             continue;
         }
-        
+
         Console::error($resource->getName().' '.$resource->getInternalId().' '.$resource->getMessage());
     }
 }
diff --git a/src/Migration/Cache.php b/src/Migration/Cache.php
index d3307c09..1eb505c7 100644
--- a/src/Migration/Cache.php
+++ b/src/Migration/Cache.php
@@ -2,7 +2,6 @@
 
 namespace Utopia\Migration;
 
-use Utopia\Migration\Resources\Functions\Func;
 use Utopia\Migration\Resources\Storage\File;
 
 /**

From 3f92f0d72af5337f6819d1ab2576a515dd4d2307 Mon Sep 17 00:00:00 2001
From: Christy Jacob <christyjacob4@gmail.com>
Date: Wed, 13 Sep 2023 21:16:19 +0000
Subject: [PATCH 6/7] chore: linter

---
 src/Migration/Sources/Appwrite.php | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/Migration/Sources/Appwrite.php b/src/Migration/Sources/Appwrite.php
index 7aeb32e7..0a8692d7 100644
--- a/src/Migration/Sources/Appwrite.php
+++ b/src/Migration/Sources/Appwrite.php
@@ -224,7 +224,7 @@ public function report(array $resources = []): array
                         $currentFiles = $storageClient->listFiles($bucket['$id'], $lastFile ? [Query::cursorAfter($lastFile)] : [Query::limit(20)])['files'];
                         $files = array_merge($files, $currentFiles);
                         $lastFile = $files[count($files) - 1]['$id'];
-    
+
                         if (count($currentFiles) < 20) {
                             break;
                         }
@@ -1121,7 +1121,7 @@ private function exportDeploymentData(Func $func, array $deployment)
         );
 
         // Content-Length header was missing, file is less than max buffer size.
-        if (!key_exists('Content-Length', $responseHeaders)) {
+        if (! array_key_exists('Content-Length', $responseHeaders)) {
             $file = $this->call(
                 'GET',
                 "/functions/{$func->getId()}/deployments/{$deployment['$id']}/download",

From 4738420632848d941620ed905613f71634df47b3 Mon Sep 17 00:00:00 2001
From: Bradley Schofield <ionicisere@gmail.com>
Date: Thu, 14 Sep 2023 10:36:34 +0100
Subject: [PATCH 7/7] Fix User Types

---
 src/Migration/Sources/Appwrite.php | 4 ++--
 src/Migration/Sources/Firebase.php | 5 +++--
 src/Migration/Sources/NHost.php    | 1 +
 src/Migration/Sources/Supabase.php | 1 +
 4 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/src/Migration/Sources/Appwrite.php b/src/Migration/Sources/Appwrite.php
index 7aeb32e7..0a8692d7 100644
--- a/src/Migration/Sources/Appwrite.php
+++ b/src/Migration/Sources/Appwrite.php
@@ -224,7 +224,7 @@ public function report(array $resources = []): array
                         $currentFiles = $storageClient->listFiles($bucket['$id'], $lastFile ? [Query::cursorAfter($lastFile)] : [Query::limit(20)])['files'];
                         $files = array_merge($files, $currentFiles);
                         $lastFile = $files[count($files) - 1]['$id'];
-    
+
                         if (count($currentFiles) < 20) {
                             break;
                         }
@@ -1121,7 +1121,7 @@ private function exportDeploymentData(Func $func, array $deployment)
         );
 
         // Content-Length header was missing, file is less than max buffer size.
-        if (!key_exists('Content-Length', $responseHeaders)) {
+        if (! array_key_exists('Content-Length', $responseHeaders)) {
             $file = $this->call(
                 'GET',
                 "/functions/{$func->getId()}/deployments/{$deployment['$id']}/download",
diff --git a/src/Migration/Sources/Firebase.php b/src/Migration/Sources/Firebase.php
index 718952e8..66ff580f 100644
--- a/src/Migration/Sources/Firebase.php
+++ b/src/Migration/Sources/Firebase.php
@@ -94,11 +94,11 @@ private function authenticate()
         }
     }
 
-    protected function call(string $method, string $path = '', array $headers = [], array $params = []): array|string
+    protected function call(string $method, string $path = '', array $headers = [], array $params = [], &$responseHeaders = []): array|string
     {
         $this->authenticate();
 
-        return parent::call($method, $path, $headers, $params);
+        return parent::call($method, $path, $headers, $params, $responseHeaders);
     }
 
     /**
@@ -210,6 +210,7 @@ private function exportUsers(int $batchSize)
                     new Hash($user['passwordHash'] ?? '', $user['salt'] ?? '', Hash::ALGORITHM_SCRYPT_MODIFIED, $hashConfig['saltSeparator'] ?? '', $hashConfig['signerKey'] ?? ''),
                     $user['phoneNumber'] ?? '',
                     $this->calculateUserType($user['providerUserInfo'] ?? []),
+                    [],
                     '',
                     $user['emailVerified'],
                     false, // Can't get phone number status on firebase :/
diff --git a/src/Migration/Sources/NHost.php b/src/Migration/Sources/NHost.php
index 91e61327..754613e6 100644
--- a/src/Migration/Sources/NHost.php
+++ b/src/Migration/Sources/NHost.php
@@ -247,6 +247,7 @@ private function exportUsers(int $batchSize)
                     new Hash($user['password_hash'], '', Hash::ALGORITHM_BCRYPT),
                     $user['phone_number'] ?? '',
                     $this->calculateUserTypes($user),
+                    [],
                     '',
                     $user['email_verified'],
                     $user['phone_number_verified'],
diff --git a/src/Migration/Sources/Supabase.php b/src/Migration/Sources/Supabase.php
index 7cdbe7f8..c1d5dc71 100644
--- a/src/Migration/Sources/Supabase.php
+++ b/src/Migration/Sources/Supabase.php
@@ -383,6 +383,7 @@ private function exportUsers(int $batchSize)
                     new Hash($user['encrypted_password'], '', Hash::ALGORITHM_BCRYPT),
                     $user['phone'] ?? '',
                     $this->calculateAuthTypes($user),
+                    [],
                     '',
                     ! empty($user['email_confirmed_at']),
                     ! empty($user['phone_confirmed_at']),
