1
0
Fork 0
mirror of synced 2024-06-13 08:14:46 +12:00

leftover commits

This commit is contained in:
Torsten Dittmann 2021-12-08 18:50:04 +01:00
parent 34e80acb7f
commit 3f92e6991a
4 changed files with 875 additions and 110 deletions

262
composer.lock generated
View file

@ -489,16 +489,16 @@
},
{
"name": "guzzlehttp/guzzle",
"version": "7.4.0",
"version": "7.4.1",
"source": {
"type": "git",
"url": "https://github.com/guzzle/guzzle.git",
"reference": "868b3571a039f0ebc11ac8f344f4080babe2cb94"
"reference": "ee0a041b1760e6a53d2a39c8c34115adc2af2c79"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/868b3571a039f0ebc11ac8f344f4080babe2cb94",
"reference": "868b3571a039f0ebc11ac8f344f4080babe2cb94",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/ee0a041b1760e6a53d2a39c8c34115adc2af2c79",
"reference": "ee0a041b1760e6a53d2a39c8c34115adc2af2c79",
"shasum": ""
},
"require": {
@ -507,7 +507,7 @@
"guzzlehttp/psr7": "^1.8.3 || ^2.1",
"php": "^7.2.5 || ^8.0",
"psr/http-client": "^1.0",
"symfony/deprecation-contracts": "^2.2"
"symfony/deprecation-contracts": "^2.2 || ^3.0"
},
"provide": {
"psr/http-client-implementation": "1.0"
@ -593,7 +593,7 @@
],
"support": {
"issues": "https://github.com/guzzle/guzzle/issues",
"source": "https://github.com/guzzle/guzzle/tree/7.4.0"
"source": "https://github.com/guzzle/guzzle/tree/7.4.1"
},
"funding": [
{
@ -609,7 +609,7 @@
"type": "tidelift"
}
],
"time": "2021-10-18T09:52:00+00:00"
"time": "2021-12-06T18:43:05+00:00"
},
{
"name": "guzzlehttp/promises",
@ -1591,25 +1591,25 @@
},
{
"name": "symfony/deprecation-contracts",
"version": "v2.5.0",
"version": "v3.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/deprecation-contracts.git",
"reference": "6f981ee24cf69ee7ce9736146d1c57c2780598a8"
"reference": "c726b64c1ccfe2896cb7df2e1331c357ad1c8ced"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/6f981ee24cf69ee7ce9736146d1c57c2780598a8",
"reference": "6f981ee24cf69ee7ce9736146d1c57c2780598a8",
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/c726b64c1ccfe2896cb7df2e1331c357ad1c8ced",
"reference": "c726b64c1ccfe2896cb7df2e1331c357ad1c8ced",
"shasum": ""
},
"require": {
"php": ">=7.1"
"php": ">=8.0.2"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "2.5-dev"
"dev-main": "3.0-dev"
},
"thanks": {
"name": "symfony/contracts",
@ -1638,7 +1638,7 @@
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.0"
"source": "https://github.com/symfony/deprecation-contracts/tree/v3.0.0"
},
"funding": [
{
@ -1654,7 +1654,7 @@
"type": "tidelift"
}
],
"time": "2021-07-12T14:48:14+00:00"
"time": "2021-11-01T23:48:49+00:00"
},
{
"name": "symfony/polyfill-ctype",
@ -3061,6 +3061,77 @@
},
"time": "2021-11-12T11:09:38+00:00"
},
{
"name": "composer/pcre",
"version": "1.0.0",
"source": {
"type": "git",
"url": "https://github.com/composer/pcre.git",
"reference": "3d322d715c43a1ac36c7fe215fa59336265500f2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/pcre/zipball/3d322d715c43a1ac36c7fe215fa59336265500f2",
"reference": "3d322d715c43a1ac36c7fe215fa59336265500f2",
"shasum": ""
},
"require": {
"php": "^5.3.2 || ^7.0 || ^8.0"
},
"require-dev": {
"phpstan/phpstan": "^1",
"phpstan/phpstan-strict-rules": "^1.1",
"symfony/phpunit-bridge": "^4.2 || ^5"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"Composer\\Pcre\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be",
"homepage": "http://seld.be"
}
],
"description": "PCRE wrapping library that offers type-safe preg_* replacements.",
"keywords": [
"PCRE",
"preg",
"regex",
"regular expression"
],
"support": {
"issues": "https://github.com/composer/pcre/issues",
"source": "https://github.com/composer/pcre/tree/1.0.0"
},
"funding": [
{
"url": "https://packagist.com",
"type": "custom"
},
{
"url": "https://github.com/composer",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/composer/composer",
"type": "tidelift"
}
],
"time": "2021-12-06T15:17:27+00:00"
},
{
"name": "composer/semver",
"version": "3.2.6",
@ -3144,25 +3215,27 @@
},
{
"name": "composer/xdebug-handler",
"version": "2.0.2",
"version": "2.0.3",
"source": {
"type": "git",
"url": "https://github.com/composer/xdebug-handler.git",
"reference": "84674dd3a7575ba617f5a76d7e9e29a7d3891339"
"reference": "6555461e76962fd0379c444c46fd558a0fcfb65e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/xdebug-handler/zipball/84674dd3a7575ba617f5a76d7e9e29a7d3891339",
"reference": "84674dd3a7575ba617f5a76d7e9e29a7d3891339",
"url": "https://api.github.com/repos/composer/xdebug-handler/zipball/6555461e76962fd0379c444c46fd558a0fcfb65e",
"reference": "6555461e76962fd0379c444c46fd558a0fcfb65e",
"shasum": ""
},
"require": {
"composer/pcre": "^1",
"php": "^5.3.2 || ^7.0 || ^8.0",
"psr/log": "^1 || ^2 || ^3"
},
"require-dev": {
"phpstan/phpstan": "^0.12.55",
"symfony/phpunit-bridge": "^4.2 || ^5"
"phpstan/phpstan": "^1.0",
"phpstan/phpstan-strict-rules": "^1.1",
"symfony/phpunit-bridge": "^4.2 || ^5.0 || ^6.0"
},
"type": "library",
"autoload": {
@ -3188,7 +3261,7 @@
"support": {
"irc": "irc://irc.freenode.org/composer",
"issues": "https://github.com/composer/xdebug-handler/issues",
"source": "https://github.com/composer/xdebug-handler/tree/2.0.2"
"source": "https://github.com/composer/xdebug-handler/tree/2.0.3"
},
"funding": [
{
@ -3204,7 +3277,7 @@
"type": "tidelift"
}
],
"time": "2021-07-31T17:03:58+00:00"
"time": "2021-12-08T13:07:32+00:00"
},
{
"name": "dnoegel/php-xdg-base-dir",
@ -3655,16 +3728,16 @@
},
{
"name": "nikic/php-parser",
"version": "v4.13.1",
"version": "v4.13.2",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
"reference": "63a79e8daa781cac14e5195e63ed8ae231dd10fd"
"reference": "210577fe3cf7badcc5814d99455df46564f3c077"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/63a79e8daa781cac14e5195e63ed8ae231dd10fd",
"reference": "63a79e8daa781cac14e5195e63ed8ae231dd10fd",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/210577fe3cf7badcc5814d99455df46564f3c077",
"reference": "210577fe3cf7badcc5814d99455df46564f3c077",
"shasum": ""
},
"require": {
@ -3705,9 +3778,9 @@
],
"support": {
"issues": "https://github.com/nikic/PHP-Parser/issues",
"source": "https://github.com/nikic/PHP-Parser/tree/v4.13.1"
"source": "https://github.com/nikic/PHP-Parser/tree/v4.13.2"
},
"time": "2021-11-03T20:52:16+00:00"
"time": "2021-11-30T19:35:32+00:00"
},
{
"name": "openlss/lib-array2xml",
@ -4035,16 +4108,16 @@
},
{
"name": "phpspec/prophecy",
"version": "1.14.0",
"version": "v1.15.0",
"source": {
"type": "git",
"url": "https://github.com/phpspec/prophecy.git",
"reference": "d86dfc2e2a3cd366cee475e52c6bb3bbc371aa0e"
"reference": "bbcd7380b0ebf3961ee21409db7b38bc31d69a13"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/d86dfc2e2a3cd366cee475e52c6bb3bbc371aa0e",
"reference": "d86dfc2e2a3cd366cee475e52c6bb3bbc371aa0e",
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/bbcd7380b0ebf3961ee21409db7b38bc31d69a13",
"reference": "bbcd7380b0ebf3961ee21409db7b38bc31d69a13",
"shasum": ""
},
"require": {
@ -4096,22 +4169,22 @@
],
"support": {
"issues": "https://github.com/phpspec/prophecy/issues",
"source": "https://github.com/phpspec/prophecy/tree/1.14.0"
"source": "https://github.com/phpspec/prophecy/tree/v1.15.0"
},
"time": "2021-09-10T09:02:12+00:00"
"time": "2021-12-08T12:19:24+00:00"
},
{
"name": "phpunit/php-code-coverage",
"version": "9.2.9",
"version": "9.2.10",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "f301eb1453c9e7a1bc912ee8b0ea9db22c60223b"
"reference": "d5850aaf931743067f4bfc1ae4cbd06468400687"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/f301eb1453c9e7a1bc912ee8b0ea9db22c60223b",
"reference": "f301eb1453c9e7a1bc912ee8b0ea9db22c60223b",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/d5850aaf931743067f4bfc1ae4cbd06468400687",
"reference": "d5850aaf931743067f4bfc1ae4cbd06468400687",
"shasum": ""
},
"require": {
@ -4167,7 +4240,7 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.9"
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.10"
},
"funding": [
{
@ -4175,20 +4248,20 @@
"type": "github"
}
],
"time": "2021-11-19T15:21:02+00:00"
"time": "2021-12-05T09:12:13+00:00"
},
{
"name": "phpunit/php-file-iterator",
"version": "3.0.5",
"version": "3.0.6",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-file-iterator.git",
"reference": "aa4be8575f26070b100fccb67faabb28f21f66f8"
"reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/aa4be8575f26070b100fccb67faabb28f21f66f8",
"reference": "aa4be8575f26070b100fccb67faabb28f21f66f8",
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf",
"reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf",
"shasum": ""
},
"require": {
@ -4227,7 +4300,7 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-file-iterator/issues",
"source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.5"
"source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6"
},
"funding": [
{
@ -4235,7 +4308,7 @@
"type": "github"
}
],
"time": "2020-09-28T05:57:25+00:00"
"time": "2021-12-02T12:48:52+00:00"
},
{
"name": "phpunit/php-invoker",
@ -4523,22 +4596,27 @@
},
{
"name": "psr/container",
"version": "1.1.2",
"version": "2.0.2",
"source": {
"type": "git",
"url": "https://github.com/php-fig/container.git",
"reference": "513e0666f7216c7459170d56df27dfcefe1689ea"
"reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea",
"reference": "513e0666f7216c7459170d56df27dfcefe1689ea",
"url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963",
"reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963",
"shasum": ""
},
"require": {
"php": ">=7.4.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Container\\": "src/"
@ -4565,9 +4643,9 @@
],
"support": {
"issues": "https://github.com/php-fig/container/issues",
"source": "https://github.com/php-fig/container/tree/1.1.2"
"source": "https://github.com/php-fig/container/tree/2.0.2"
},
"time": "2021-11-05T16:50:12+00:00"
"time": "2021-11-05T16:47:00+00:00"
},
{
"name": "sebastian/cli-parser",
@ -5587,28 +5665,29 @@
},
{
"name": "symfony/console",
"version": "v5.3.11",
"version": "v5.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "3e7ab8f5905058984899b05a4648096f558bfeba"
"reference": "ec3661faca1d110d6c307e124b44f99ac54179e3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/3e7ab8f5905058984899b05a4648096f558bfeba",
"reference": "3e7ab8f5905058984899b05a4648096f558bfeba",
"url": "https://api.github.com/repos/symfony/console/zipball/ec3661faca1d110d6c307e124b44f99ac54179e3",
"reference": "ec3661faca1d110d6c307e124b44f99ac54179e3",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
"symfony/deprecation-contracts": "^2.1",
"symfony/deprecation-contracts": "^2.1|^3",
"symfony/polyfill-mbstring": "~1.0",
"symfony/polyfill-php73": "^1.8",
"symfony/polyfill-php80": "^1.16",
"symfony/service-contracts": "^1.1|^2",
"symfony/string": "^5.1"
"symfony/service-contracts": "^1.1|^2|^3",
"symfony/string": "^5.1|^6.0"
},
"conflict": {
"psr/log": ">=3",
"symfony/dependency-injection": "<4.4",
"symfony/dotenv": "<5.1",
"symfony/event-dispatcher": "<4.4",
@ -5620,12 +5699,12 @@
},
"require-dev": {
"psr/log": "^1|^2",
"symfony/config": "^4.4|^5.0",
"symfony/dependency-injection": "^4.4|^5.0",
"symfony/event-dispatcher": "^4.4|^5.0",
"symfony/lock": "^4.4|^5.0",
"symfony/process": "^4.4|^5.0",
"symfony/var-dumper": "^4.4|^5.0"
"symfony/config": "^4.4|^5.0|^6.0",
"symfony/dependency-injection": "^4.4|^5.0|^6.0",
"symfony/event-dispatcher": "^4.4|^5.0|^6.0",
"symfony/lock": "^4.4|^5.0|^6.0",
"symfony/process": "^4.4|^5.0|^6.0",
"symfony/var-dumper": "^4.4|^5.0|^6.0"
},
"suggest": {
"psr/log": "For using the console logger",
@ -5665,7 +5744,7 @@
"terminal"
],
"support": {
"source": "https://github.com/symfony/console/tree/v5.3.11"
"source": "https://github.com/symfony/console/tree/v5.4.0"
},
"funding": [
{
@ -5681,7 +5760,7 @@
"type": "tidelift"
}
],
"time": "2021-11-21T19:41:05+00:00"
"time": "2021-11-29T15:30:56+00:00"
},
{
"name": "symfony/polyfill-intl-grapheme",
@ -6009,22 +6088,21 @@
},
{
"name": "symfony/service-contracts",
"version": "v2.5.0",
"version": "v3.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/service-contracts.git",
"reference": "1ab11b933cd6bc5464b08e81e2c5b07dec58b0fc"
"reference": "36715ebf9fb9db73db0cb24263c79077c6fe8603"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/1ab11b933cd6bc5464b08e81e2c5b07dec58b0fc",
"reference": "1ab11b933cd6bc5464b08e81e2c5b07dec58b0fc",
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/36715ebf9fb9db73db0cb24263c79077c6fe8603",
"reference": "36715ebf9fb9db73db0cb24263c79077c6fe8603",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
"psr/container": "^1.1",
"symfony/deprecation-contracts": "^2.1"
"php": ">=8.0.2",
"psr/container": "^2.0"
},
"conflict": {
"ext-psr": "<1.1|>=2"
@ -6035,7 +6113,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "2.5-dev"
"dev-main": "3.0-dev"
},
"thanks": {
"name": "symfony/contracts",
@ -6072,7 +6150,7 @@
"standards"
],
"support": {
"source": "https://github.com/symfony/service-contracts/tree/v2.5.0"
"source": "https://github.com/symfony/service-contracts/tree/v3.0.0"
},
"funding": [
{
@ -6088,35 +6166,37 @@
"type": "tidelift"
}
],
"time": "2021-11-04T16:48:04+00:00"
"time": "2021-11-04T17:53:12+00:00"
},
{
"name": "symfony/string",
"version": "v5.3.10",
"version": "v6.0.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
"reference": "d70c35bb20bbca71fc4ab7921e3c6bda1a82a60c"
"reference": "ba727797426af0f587f4800566300bdc0cda0777"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/string/zipball/d70c35bb20bbca71fc4ab7921e3c6bda1a82a60c",
"reference": "d70c35bb20bbca71fc4ab7921e3c6bda1a82a60c",
"url": "https://api.github.com/repos/symfony/string/zipball/ba727797426af0f587f4800566300bdc0cda0777",
"reference": "ba727797426af0f587f4800566300bdc0cda0777",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
"php": ">=8.0.2",
"symfony/polyfill-ctype": "~1.8",
"symfony/polyfill-intl-grapheme": "~1.0",
"symfony/polyfill-intl-normalizer": "~1.0",
"symfony/polyfill-mbstring": "~1.0",
"symfony/polyfill-php80": "~1.15"
"symfony/polyfill-mbstring": "~1.0"
},
"conflict": {
"symfony/translation-contracts": "<2.0"
},
"require-dev": {
"symfony/error-handler": "^4.4|^5.0",
"symfony/http-client": "^4.4|^5.0",
"symfony/translation-contracts": "^1.1|^2",
"symfony/var-exporter": "^4.4|^5.0"
"symfony/error-handler": "^5.4|^6.0",
"symfony/http-client": "^5.4|^6.0",
"symfony/translation-contracts": "^2.0|^3.0",
"symfony/var-exporter": "^5.4|^6.0"
},
"type": "library",
"autoload": {
@ -6155,7 +6235,7 @@
"utf8"
],
"support": {
"source": "https://github.com/symfony/string/tree/v5.3.10"
"source": "https://github.com/symfony/string/tree/v6.0.0"
},
"funding": [
{
@ -6171,7 +6251,7 @@
"type": "tidelift"
}
],
"time": "2021-10-27T18:21:46+00:00"
"time": "2021-10-29T07:35:21+00:00"
},
{
"name": "textalk/websocket",

View file

@ -91,6 +91,26 @@ class Document extends ArrayObject
return $temp;
}
/**
* Get Document Attributes
*
* @return array
*/
public function getAttributes(): array
{
$attributes = [];
foreach ($this as $attribute => $value) {
if(array_key_exists($attribute, ['$id' => true, '$permissions' => true, '$collection' => true, '$execute' => []])) {
continue;
}
$attributes[$attribute] = $value;
}
return $attributes;
}
/**
* Set Attribute.
*
@ -215,7 +235,7 @@ class Document extends ArrayObject
*
* @return array
*/
public function getArrayCopy(array $whitelist = [], array $blacklist = [])
public function getArrayCopy(array $whitelist = [], array $blacklist = []): array
{
$array = parent::getArrayCopy();

View file

@ -2,9 +2,10 @@
namespace Appwrite\Migration;
use Appwrite\Database\Document;
use Appwrite\Database\Database;
use Appwrite\Database\Document as OldDocument;
use Appwrite\Database\Database as OldDatabase;
use PDO;
use Redis;
use Swoole\Runtime;
use Utopia\CLI\Console;
use Utopia\Exception;
@ -14,22 +15,32 @@ abstract class Migration
/**
* @var PDO
*/
protected $db;
protected PDO $db;
/**
* @var Redis
*/
protected Redis $cache;
/**
* @var int
*/
protected $limit = 50;
protected int $limit = 50;
/**
* @var Document
* @var OldDocument
*/
protected $project;
protected OldDocument $project;
/**
* @var Database
* @var OldDatabase
*/
protected $projectDB;
protected OldDatabase $oldProjectDB;
/**
* @var OldDatabase
*/
protected OldDatabase $oldConsoleDB;
/**
* @var array
@ -49,7 +60,7 @@ abstract class Migration
'0.10.3' => 'V09',
'0.10.4' => 'V09',
'0.11.0' => 'V10',
'0.12.0' => 'V10',
'0.12.0' => 'V11',
];
/**
@ -57,24 +68,32 @@ abstract class Migration
*
* @param PDO $pdo
*/
public function __construct(PDO $db)
public function __construct(PDO $db, Redis $cache = null)
{
$this->db = $db;
if(!is_null($cache)) {
$this->cache = $cache;
}
}
/**
* Set project for migration.
*
* @param Document $project
* @param Database $projectDB
* @param OldDocument $project
* @param OldDatabase $projectDB
* @param OldDatabase $oldConsoleDB
*
* @return Migration
* @return self
*/
public function setProject(Document $project, Database $projectDB): Migration
public function setProject(OldDocument $project, OldDatabase $projectDB, OldDatabase $oldConsoleDB): self
{
$this->project = $project;
$this->projectDB = $projectDB;
$this->projectDB->setNamespace('app_' . $project->getId());
$this->oldProjectDB = $projectDB;
$this->oldProjectDB->setNamespace('app_' . $project->getId());
$this->oldConsoleDB = $oldConsoleDB;
return $this;
}
@ -117,7 +136,7 @@ abstract class Migration
}
try {
$new = $this->projectDB->overwriteDocument($document->getArrayCopy());
$new = $this->projectDB->overwriteDocument($new->getArrayCopy());
} catch (\Throwable $th) {
Console::error('Failed to update document: ' . $th->getMessage());
return;
@ -134,7 +153,14 @@ abstract class Migration
}
}
public function check_diff_multi($array1, $array2)
/**
* Checks 2 arrays for differences.
*
* @param array $array1
* @param array $array2
* @return array
*/
public function check_diff_multi(array $array1, array $array2)
{
$result = array();

View file

@ -0,0 +1,639 @@
<?php
namespace Appwrite\Migration\Version;
use Appwrite\Database\Database as OldDatabase;
use Appwrite\Database\Document as OldDocument;
use Appwrite\Migration\Migration;
use Exception;
use PDO;
use Redis;
use Swoole\Runtime;
use Utopia\Abuse\Adapters\TimeLimit;
use Utopia\Audit\Audit;
use Utopia\Cache\Cache;
use Utopia\CLI\Console;
use Utopia\Cache\Adapter\Redis as RedisCache;
use Utopia\Config\Config;
use Utopia\Database\Adapter\MariaDB;
use Utopia\Database\Database;
use Utopia\Database\Document;
use Utopia\Database\Query;
use Utopia\Database\Validator\Authorization;
global $register;
class V11 extends Migration
{
protected Database $dbInternal;
protected Database $dbExternal;
protected Database $dbConsole;
protected array $oldCollections;
protected array $newCollections;
public function __construct(PDO $db, Redis $cache = null)
{
parent::__construct($db, $cache);
if (!is_null($cache)) {
$cacheAdapter = new Cache(new RedisCache($this->cache));
$this->dbInternal = new Database(new MariaDB($this->db), $cacheAdapter);
$this->dbExternal = new Database(new MariaDB($this->db), $cacheAdapter);
$this->dbConsole = new Database(new MariaDB($this->db), $cacheAdapter);
$this->dbConsole->setNamespace('project_console_internal');
}
$this->newCollections = Config::getParam('collections', []);
$this->oldCollections = Config::getParam('collectionsold', []);
}
public function execute(): void
{
Authorization::disable();
Runtime::enableCoroutine(SWOOLE_HOOK_ALL);
/**
* Get a project to check if the version works with this migration.
*/
if (!str_starts_with($this->oldConsoleDB->getCollectionFirst([
'filters' => [
'$collection=' . OldDatabase::SYSTEM_COLLECTION_PROJECTS
]
])->getAttribute('version'), '0.11.')) {
throw new Exception("Can only migrate from version 0.11.x to 0.12.x");
}
$oldProject = $this->project;
$this->dbInternal->setNamespace('project_' . $oldProject->getId() . '_internal');
$this->dbExternal->setNamespace('project_' . $oldProject->getId() . '_external');
/**
* Create internal/external structure for projects and skip the console project.
*/
if ($oldProject->getId() !== 'console') {
$project = $this->dbConsole->getDocument('projects', $oldProject->getId());
/**
* Migrate Project Document.
*/
if ($project->isEmpty()) {
$newProject = $this->fixDocument($oldProject);
$newProject->setAttribute('version', '0.12.0');
$project = $this->dbConsole->createDocument('projects', $newProject);
Console::log('Migrating project: ' . $oldProject->getAttribute('name') . ' (' . $oldProject->getId() . ')');
}
/**
* Create internal DB tables
*/
if (!$this->dbInternal->exists()) {
$this->dbInternal->create();
Console::log('Created internal tables for : ' . $project->getAttribute('name') . ' (' . $project->getId() . ')');
}
/**
* Create external DB tables
*/
if (!$this->dbExternal->exists()) {
$this->dbExternal->create();
Console::log('Created external tables for : ' . $project->getAttribute('name') . ' (' . $project->getId() . ')');
}
/**
* Create Audit tables
*/
if ($this->dbInternal->getCollection(Audit::COLLECTION)->isEmpty()) {
$audit = new Audit($this->dbInternal);
$audit->setup();
Console::log('Created audit tables for : ' . $project->getAttribute('name') . ' (' . $project->getId() . ')');
}
/**
* Create Abuse tables
*/
if ($this->dbInternal->getCollection(TimeLimit::COLLECTION)->isEmpty()) {
$adapter = new TimeLimit("", 0, 1, $this->dbInternal);
$adapter->setup();
Console::log('Created abuse tables for : ' . $project->getAttribute('name') . ' (' . $project->getId() . ')');
}
/**
* Create internal collections for Project
*/
foreach ($this->newCollections as $key => $collection) {
if (!$this->dbInternal->getCollection($key)->isEmpty()) continue; // Skip if project collection already exists
$attributes = [];
$indexes = [];
foreach ($collection['attributes'] as $attribute) {
$attributes[] = new Document([
'$id' => $attribute['$id'],
'type' => $attribute['type'],
'size' => $attribute['size'],
'required' => $attribute['required'],
'signed' => $attribute['signed'],
'array' => $attribute['array'],
'filters' => $attribute['filters'],
]);
}
foreach ($collection['indexes'] as $index) {
$indexes[] = new Document([
'$id' => $index['$id'],
'type' => $index['type'],
'attributes' => $index['attributes'],
'lengths' => $index['lengths'],
'orders' => $index['orders'],
]);
}
$this->dbInternal->createCollection($key, $attributes, $indexes);
}
$sum = $this->limit;
$offset = 0;
/**
* Migrate external collections for Project
*/
while ($sum >= $this->limit) {
$databaseCollections = $this->oldProjectDB->getCollection([
'limit' => $this->limit,
'offset' => $offset,
'orderType' => 'DESC',
'filters' => [
'$collection=' . OldDatabase::SYSTEM_COLLECTION_COLLECTIONS,
]
]);
$sum = \count($databaseCollections);
Console::log('Migrating Collections: ' . $offset . ' / ' . $this->oldProjectDB->getSum());
foreach ($databaseCollections as $oldCollection) {
$id = $oldCollection->getId();
$permissions = $oldCollection->getPermissions();
$name = $oldCollection->getAttribute('name');
$newCollection = $this->dbExternal->getCollection($id);
if ($newCollection->isEmpty()) {
$this->dbExternal->createCollection($id);
/**
* Migrate permissions
*/
$read = $this->migrateWildcardPermissions($permissions['read'] ?? []);
$write = $this->migrateWildcardPermissions($permissions['write'] ?? []);
/**
* Suffix collection name with a subsequent number to make it unique if possible.
*/
$suffix = 1;
while ($this->dbInternal->findOne('collections', [
new Query('name', Query::TYPE_EQUAL, [$name])
])) {
$name .= ' - ' . $suffix++;
}
$this->dbInternal->createDocument('collections', new Document([
'$id' => $id,
'$read' => $read,
'$write' => $write,
'permission' => 'document',
'dateCreated' => time(),
'dateUpdated' => time(),
'name' => $name,
'search' => implode(' ', [$id, $name]),
]));
} else {
Console::warning('Skipped Collection ' . $newCollection->getId() . ' from ' . $newCollection->getCollection());
}
/**
* Migrate collection rules to attributes
*/
$attributes = $this->getCollectionAttributes($oldCollection);
foreach ($attributes as $attribute) {
try {
$this->dbExternal->createAttribute(
collection: $attribute['$collection'],
id: $attribute['$id'],
type: $attribute['type'],
size: $attribute['size'],
required: $attribute['required'],
default: $attribute['default'],
signed: $attribute['signed'],
array: $attribute['array'],
format: null,
filters: $attribute['filters']
);
$this->dbInternal->createDocument('attributes', new Document([
'$id' => $attribute['$collection'] . '_' . $attribute['$id'],
'key' => $attribute['$id'],
'collectionId' => $attribute['$collection'],
'type' => $attribute['type'],
'status' => 'available',
'size' => $attribute['size'],
'required' => $attribute['required'],
'signed' => $attribute['signed'],
'default' => $attribute['default'],
'array' => $attribute['array'],
'format' => null,
'filters' => $attribute['filters']
]));
Console::log('Created "' . $attribute['$id'] . '" attribute in collection: ' . $name);
} catch (\Throwable $th) {
Console::log($th->getMessage() . ' - (' . $attribute['$id'] . '" attribute in collection ' . $name . ')');
}
}
/**
* Migrate all external documents
*/
$sumDocs = $this->limit;
$offsetDocs = 0;
while ($sumDocs >= $this->limit) {
$allDocs = $this->oldProjectDB->getCollection([
'limit' => $this->limit,
'offset' => $offsetDocs,
'orderType' => 'DESC',
'filters' => [
'$collection=' . $id
]
]);
$sumDocs = \count($allDocs);
foreach ($allDocs as $document) {
if (!$this->dbExternal->getDocument($id, $document->getId())->isEmpty()) {
continue;
}
foreach ($document as $key => $attr) {
/**
* Convert nested Document to JSON strings.
*/
if ($document->getAttribute($key) instanceof OldDocument) {
$document[$key] = json_encode($this->fixDocument($attr)->getArrayCopy());
}
/**
* Convert numeric Attributes to float.
*/
if (is_numeric($attr)) {
$document[$key] = floatval($attr);
}
if (\is_array($attr)) {
foreach ($attr as $index => $child) {
/**
* Convert array of nested Document to array JSON strings.
*/
if ($document->getAttribute($key)[$index] instanceof OldDocument) {
$document[$key][$index] = json_encode($this->fixDocument($child)->getArrayCopy());
}
/**
* Convert array of numeric Attributes to array float.
*/
if (is_numeric($attr)) {
$document[$key][$index] = floatval($child); // Convert any numeric to float
}
}
}
}
$document = new Document($document->getArrayCopy());
$document = $this->migratePermissions($document);
$this->dbExternal->createDocument($id, $document);
}
$offsetDocs += $this->limit;
}
}
$offset += $this->limit;
}
} else {
Console::log('Skipped console project migration.');
}
$sum = $this->limit;
$offset = 0;
Authorization::disable();
/**
* Migrate internal documents
*/
while ($sum >= $this->limit) {
$all = $this->oldProjectDB->getCollection([
'limit' => $this->limit,
'offset' => $offset,
'orderType' => 'DESC',
'filters' => [
'$collection!=' . OldDatabase::SYSTEM_COLLECTION_COLLECTIONS,
'$collection!=' . OldDatabase::SYSTEM_COLLECTION_RULES,
'$collection!=' . OldDatabase::SYSTEM_COLLECTION_TASKS,
'$collection!=' . OldDatabase::SYSTEM_COLLECTION_PROJECTS,
'$collection!=' . OldDatabase::SYSTEM_COLLECTION_CONNECTIONS,
]
]);
$sum = \count($all);
Console::log('Migrating Documents: ' . $offset . ' / ' . $this->oldProjectDB->getSum());
foreach ($all as $document) {
if (
!array_key_exists($document->getCollection(), $this->oldCollections)
) {
continue;
}
$old = $document->getArrayCopy();
$new = $this->fixDocument($document);
if (empty($new->getId())) {
Console::warning('Skipped Document due to missing ID.');
continue;
}
try {
if ($this->dbInternal->getDocument($new->getCollection(), $new->getId())->isEmpty()) {
$this->dbInternal->createDocument($new->getCollection(), $new);
} else {
Console::warning('Skipped Document ' . $new->getId() . ' from ' . $new->getCollection());
}
} catch (\Throwable $th) {
Console::error('Failed to update document: ' . $th->getMessage());
continue;
if ($document && $new->getId() !== $document->getId()) {
throw new Exception('Duplication Error');
}
}
}
$offset += $this->limit;
}
Console::log('Migrated ' . $sum . ' Documents.');
}
protected function fixDocument(OldDocument $oldDocument): Document
{
$document = new Document($oldDocument->getArrayCopy());
$document = $this->migratePermissions($document);
/**
* Check attributes and set their default values.
*/
if (array_key_exists($document->getCollection(), $this->oldCollections)) {
foreach ($this->newCollections[$document->getCollection()]['attributes'] as $attr) {
if (
(!$attr['array'] ||
($attr['array'] && array_key_exists('filter', $attr)
&& in_array('json', $attr['filter'])))
&& empty($document->getAttribute($attr['$id'], null))
) {
$document->setAttribute($attr['$id'], $attr['default'] ?? null);
}
}
}
switch ($document->getAttribute('$collection')) {
case OldDatabase::SYSTEM_COLLECTION_PLATFORMS:
$projectId = $this->getProjectIdFromReadPermissions($document);
/**
* Set Project ID
*/
if ($document->getAttribute('projectId') === null) {
$document->setAttribute('projectId', $projectId);
}
/**
* Set empty key and store if null
*/
if ($document->getAttribute('key') === null) {
$document->setAttribute('key', '');
}
if ($document->getAttribute('store') === null) {
$document->setAttribute('store', '');
}
/**
* Reset Permissions
*/
$document->setAttribute('$read', ['role:all']);
$document->setAttribute('$write', ['role:all']);
break;
case OldDatabase::SYSTEM_COLLECTION_DOMAINS:
$projectId = $this->getProjectIdFromReadPermissions($document);
/**
* Set Project ID
*/
if ($document->getAttribute('projectId') === null) {
$document->setAttribute('projectId', $projectId);
}
/**
* Set empty verification if null
*/
if ($document->getAttribute('verification') === null) {
$document->setAttribute('verification', false);
}
/**
* Reset Permissions
*/
$document->setAttribute('$read', ['role:all']);
$document->setAttribute('$write', ['role:all']);
break;
case OldDatabase::SYSTEM_COLLECTION_KEYS:
case OldDatabase::SYSTEM_COLLECTION_WEBHOOKS:
$projectId = $this->getProjectIdFromReadPermissions($document);
/**
* Set Project ID
*/
if ($document->getAttribute('projectId') === null) {
$document->setAttribute('projectId', $projectId);
}
/**
* Reset Permissions
*/
$document->setAttribute('$read', ['role:all']);
$document->setAttribute('$write', ['role:all']);
break;
case OldDatabase::SYSTEM_COLLECTION_USERS:
/**
* Set deleted attribute to false
*/
if ($document->getAttribute('deleted') === null) {
$document->setAttribute('deleted', false);
}
/**
* Remove deprecated user status 0 and replace with boolean.
*/
if ($document->getAttribute('status') === 2) {
$document->setAttribute('status', false);
} else {
$document->setAttribute('status', true);
}
/**
* Set default values for arrays if not set.
*/
if (empty($document->getAttribute('prefs', []))) {
$document->setAttribute('prefs', []);
}
if (empty($document->getAttribute('sessions', []))) {
$document->setAttribute('sessions', []);
}
if (empty($document->getAttribute('tokens', []))) {
$document->setAttribute('tokens', []);
}
if (empty($document->getAttribute('memberships', []))) {
$document->setAttribute('memberships', []);
}
/**
* Replace user:{self} with user:USER_ID
*/
$write = $document->getWrite();
$document->setAttribute('$write', str_replace('user:{self}', "user:{$document->getId()}", $write));
break;
case OldDatabase::SYSTEM_COLLECTION_FILES:
/**
* Migrating breakind changes on Files.
*/
if (!empty($document->getAttribute('fileOpenSSLVersion', null))) {
$document
->setAttribute('openSSLVersion', $document->getAttribute('fileOpenSSLVersion'))
->removeAttribute('fileOpenSSLVersion');
}
if (!empty($document->getAttribute('fileOpenSSLCipher', null))) {
$document
->setAttribute('openSSLCipher', $document->getAttribute('fileOpenSSLCipher'))
->removeAttribute('fileOpenSSLCipher');
}
if (!empty($document->getAttribute('fileOpenSSLTag', null))) {
$document
->setAttribute('openSSLTag', $document->getAttribute('fileOpenSSLTag'))
->removeAttribute('fileOpenSSLTag');
}
if (!empty($document->getAttribute('fileOpenSSLIV', null))) {
$document
->setAttribute('openSSLIV', $document->getAttribute('fileOpenSSLIV'))
->removeAttribute('fileOpenSSLIV');
}
/**
* Remove deprecated attributes.
*/
$document->removeAttribute('folderId');
$document->removeAttribute('token');
break;
}
return $document;
}
/**
* Migrates $permissions to independent $read and $write.
* @param Document $document
* @return Document
*/
protected function migratePermissions(Document $document): Document
{
if ($document->isSet('$permissions')) {
$permissions = $document->getAttribute('$permissions', []);
$read = $this->migrateWildcardPermissions($permissions['read'] ?? []);
$write = $this->migrateWildcardPermissions($permissions['write'] ?? []);
$document->setAttribute('$read', $read);
$document->setAttribute('$write', $write);
$document->removeAttribute('$permissions');
}
return $document;
}
/**
* Takes a permissions array and replaces wildcard * with role:all.
* @param array $permissions
* @return array
*/
protected function migrateWildcardPermissions(array $permissions): array
{
return array_map(function ($permission) {
if ($permission === '*') return 'role:all';
return $permission;
}, $permissions);
}
/**
* Get new collection attributes from old collection rules.
* @param OldDocument $collection
* @return array
*/
protected function getCollectionAttributes(OldDocument $collection): array
{
$attributes = [];
foreach ($collection->getAttribute('rules', []) as $key => $value) {
$collectionId = $collection->getId();
$id = $value['key'];
$array = $value['array'] ?? false;
$required = $value['required'] ?? false;
$default = $value['default'] ?? null;
$default = match ($value['type']) {
OldDatabase::SYSTEM_VAR_TYPE_NUMERIC => floatval($default),
default => $default
};
$type = match ($value['type']) {
OldDatabase::SYSTEM_VAR_TYPE_TEXT => Database::VAR_STRING,
OldDatabase::SYSTEM_VAR_TYPE_EMAIL => Database::VAR_STRING,
OldDatabase::SYSTEM_VAR_TYPE_DOCUMENT => Database::VAR_STRING,
OldDatabase::SYSTEM_VAR_TYPE_IP => Database::VAR_STRING,
OldDatabase::SYSTEM_VAR_TYPE_URL => Database::VAR_STRING,
OldDatabase::SYSTEM_VAR_TYPE_WILDCARD => Database::VAR_STRING,
OldDatabase::SYSTEM_VAR_TYPE_NUMERIC => Database::VAR_FLOAT,
OldDatabase::SYSTEM_VAR_TYPE_BOOLEAN => Database::VAR_BOOLEAN,
default => Database::VAR_STRING
};
$size = $type === Database::VAR_STRING ? 65_535 : 0; // Max size of text in MariaDB
$attributes[$key] = [
'$collection' => $collectionId,
'$id' => $id,
'type' => $type,
'size' => $size,
'required' => $required,
'default' => $default,
'array' => $array,
'signed' => true,
'filters' => []
];
}
return $attributes;
}
/**
*
* @param Document $document
* @return string|null
* @throws Exception
*/
protected function getProjectIdFromReadPermissions(Document $document): string|null
{
$readPermissions = $document->getRead();
$teamId = str_replace('team:', '', reset($readPermissions));
return $this->oldConsoleDB->getCollectionFirst([
'filters' => [
'$collection=' . OldDatabase::SYSTEM_COLLECTION_PROJECTS,
'teamId=' . $teamId
]
])->getId();
}
}