diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index 5e8d2104f9..743df13b00 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -493,7 +493,7 @@ App::delete('/v1/storage/buckets/:bucketId') throw new Exception('Bucket not found', 404); } - if(!$dbForInternal->deleteDocument('buckets', $bucketId)) { + if (!$dbForInternal->deleteDocument('buckets', $bucketId)) { throw new Exception('Failed to remove project from DB', 500); } @@ -557,7 +557,7 @@ App::post('/v1/storage/buckets/:bucketId/files') $bucket = $dbForInternal->getDocument('buckets', $bucketId); - if($bucket->isEmpty() + if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN )) { throw new Exception('Bucket not found', 404); } @@ -597,7 +597,7 @@ App::post('/v1/storage/buckets/:bucketId/files') $fileSize = (\is_array($file['size']) && isset($file['size'][0])) ? $file['size'][0] : $file['size']; $contentRange = $request->getHeader('content-range'); - $fileId = $fileId === 'unique()' ? $dbForInternal->getId() : $fileId; + $fileId = $fileId === 'unique()' ? $dbForExternal->getId() : $fileId; $chunk = 1; $chunks = 1; @@ -606,7 +606,7 @@ App::post('/v1/storage/buckets/:bucketId/files') $end = $request->getContentRangeEnd(); $fileSize = $request->getContentRangeSize(); $fileId = $request->getHeader('x-appwrite-id', $fileId); - if(is_null($start) || is_null($end) || is_null($fileSize)) { + if (is_null($start) || is_null($end) || is_null($fileSize)) { throw new Exception('Invalid content-range header', 400); } @@ -694,7 +694,7 @@ App::post('/v1/storage/buckets/:bucketId/files') $data = OpenSSL::encrypt($data, OpenSSL::CIPHER_AES_128_GCM, $key, 0, $iv, $tag); } - if(!empty($data)) { + if (!empty($data)) { if (!$device->write($path, $data, $mimeType)) { throw new Exception('Failed to save file', 500); } @@ -737,7 +737,7 @@ App::post('/v1/storage/buckets/:bucketId/files') 'search' => implode(' ', [$fileId, $fileName,]), 'metadata' => $metadata, ]); - if($permissionBucket) { + if ($permissionBucket) { $file = Authorization::skip(function() use ($dbForExternal, $bucketId, $doc) { return $dbForExternal->createDocument('bucket_' . $bucketId, $doc); }); @@ -756,9 +756,10 @@ App::post('/v1/storage/buckets/:bucketId/files') ->setAttribute('openSSLCipher', $openSSLCipher) ->setAttribute('openSSLTag', $openSSLTag) ->setAttribute('openSSLIV', $openSSLIV) - ->setAttribute('metadata', $metadata); + ->setAttribute('metadata', $metadata) + ->setAttribute('chunksUploaded', $chunksUploaded); - if($permissionBucket) { + if ($permissionBucket) { $file = Authorization::skip(function() use ($dbForExternal, $bucketId, $fileId, $file) { return $dbForExternal->updateDocument('bucket_' . $bucketId, $fileId, $file); }); @@ -796,7 +797,7 @@ App::post('/v1/storage/buckets/:bucketId/files') 'search' => implode(' ', [$fileId, $fileName,]), 'metadata' => $metadata, ]); - if($permissionBucket) { + if ($permissionBucket) { $file = Authorization::skip(function() use ($dbForExternal, $bucketId, $doc) { return $dbForExternal->createDocument('bucket_' . $bucketId, $doc); }); @@ -808,7 +809,7 @@ App::post('/v1/storage/buckets/:bucketId/files') ->setAttribute('chunksUploaded', $chunksUploaded) ->setAttribute('metadata', $metadata); - if($permissionBucket) { + if ($permissionBucket) { $file = Authorization::skip(function() use ($dbForExternal, $bucketId, $fileId, $file) { return $dbForExternal->updateDocument('bucket_' . $bucketId, $fileId, $file); }); @@ -876,7 +877,7 @@ App::get('/v1/storage/buckets/:bucketId/files') $bucket = $dbForInternal->getDocument('buckets', $bucketId); - if($bucket->isEmpty() + if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN )) { throw new Exception('Bucket not found', 404); } @@ -896,7 +897,7 @@ App::get('/v1/storage/buckets/:bucketId/files') } if (!empty($cursor)) { - if($bucket->getAttribute('permission') ==='bucket') { + if ($bucket->getAttribute('permission') ==='bucket') { $cursorFile = Authorization::skip(function() use ($dbForExternal, $bucket, $cursor) { return $dbForExternal->getDocument('bucket_' . $bucket->getId(), $cursor); }); @@ -915,7 +916,7 @@ App::get('/v1/storage/buckets/:bucketId/files') $queries[] = new Query('search', Query::TYPE_SEARCH, [$search]); } - if($bucket->getAttribute('permission') === 'bucket') { + if ($bucket->getAttribute('permission') === 'bucket') { $files = Authorization::skip(function() use ($dbForExternal, $bucketId, $queries, $limit, $offset, $cursor, $cursorDirection, $orderType) { return $dbForExternal->find('bucket_' . $bucketId, $queries, $limit, $offset, [], [$orderType], $cursorFile ?? null, $cursorDirection); }); @@ -962,7 +963,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId') $bucket = $dbForInternal->getDocument('buckets', $bucketId); - if($bucket->isEmpty() + if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN )) { throw new Exception('Bucket not found', 404); } @@ -975,7 +976,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId') } } - if($bucket->getAttribute('permission') === 'bucket') { + if ($bucket->getAttribute('permission') === 'bucket') { $file = Authorization::skip(function() use ($dbForExternal, $bucketId, $fileId) { return $dbForExternal->getDocument('bucket_' . $bucketId, $fileId); }); @@ -1044,7 +1045,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') } $bucket = $dbForInternal->getDocument('buckets', $bucketId); - if($bucket->isEmpty() + if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN )) { throw new Exception('Bucket not found', 404); } @@ -1068,7 +1069,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') $date = \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)).' GMT'; // 45 days cache $key = \md5($fileId.$width.$height.$gravity.$quality.$borderWidth.$borderColor.$borderRadius.$opacity.$rotation.$background.$storage.$output); - if($bucket->getAttribute('permission')==='bucket') { + if ($bucket->getAttribute('permission')==='bucket') { // skip authorization $file = Authorization::skip(function () use ($dbForExternal, $bucketId, $fileId) { return $dbForExternal->getDocument('bucket_' . $bucketId, $fileId); @@ -1209,7 +1210,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download') $bucket = $dbForInternal->getDocument('buckets', $bucketId); - if($bucket->isEmpty() + if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN )) { throw new Exception('Bucket not found', 404); } @@ -1222,7 +1223,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download') } } - if($bucket->getAttribute('permission') === 'bucket') { + if ($bucket->getAttribute('permission') === 'bucket') { $file = Authorization::skip(function() use ($dbForExternal, $fileId, $bucketId) { return $dbForExternal->getDocument('bucket_' . $bucketId, $fileId); }); @@ -1257,16 +1258,16 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download') $size = $file->getAttribute('sizeOriginal', 0); $rangeHeader = $request->getHeader('range'); - if(!empty($rangeHeader)) { + if (!empty($rangeHeader)) { $start = $request->getRangeStart(); $end = $request->getRangeEnd(); $unit = $request->getRangeUnit(); - if($end == null) { - $end = min(($start + 2000000-1), ($size - 1)); + if ($end === null) { + $end = min(($start + MAX_OUTPUT_CHUNK_SIZE-1), ($size - 1)); } - if($unit != 'bytes' || $start >= $end || $end >= $size) { + if ($unit !== 'bytes' || $start >= $end || $end >= $size) { throw new Exception('Invalid range', 416); } @@ -1291,28 +1292,35 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download') } if (!empty($file->getAttribute('algorithm', ''))) { - if(empty($source)) { + if (empty($source)) { $source = $device->read($path); } $compressor = new GZIP(); $source = $compressor->decompress($source); } - if(!empty($source)) { - if(!empty($rangeHeader)) { + if (!empty($source)) { + if (!empty($rangeHeader)) { $response->send(substr($source, $start, ($end - $start + 1))); } $response->send($source); } - if(!empty($rangeHeader)) { + if (!empty($rangeHeader)) { $response->send($device->read($path, $start, ($end - $start + 1))); } if ($size > APP_STORAGE_READ_BUFFER) { $response->addHeader('Content-Length', $device->getFileSize($path)); for ($i=0; $i < ceil($size / MAX_OUTPUT_CHUNK_SIZE); $i++) { - $response->chunk($device->read($path, ($i * MAX_OUTPUT_CHUNK_SIZE), min(MAX_OUTPUT_CHUNK_SIZE, $size - ($i * MAX_OUTPUT_CHUNK_SIZE))), (($i + 1) * MAX_OUTPUT_CHUNK_SIZE) >= $size); + $response->chunk( + $device->read( + $path, + ($i * MAX_OUTPUT_CHUNK_SIZE), + min(MAX_OUTPUT_CHUNK_SIZE, $size - ($i * MAX_OUTPUT_CHUNK_SIZE)) + ), + (($i + 1) * MAX_OUTPUT_CHUNK_SIZE) >= $size + ); } } else { $response->send($device->read($path)); @@ -1348,7 +1356,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view') $bucket = $dbForInternal->getDocument('buckets', $bucketId); - if($bucket->isEmpty() + if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN )) { throw new Exception('Bucket not found', 404); } @@ -1361,7 +1369,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view') } } - if($bucket->getAttribute('permission') === 'bucket') { + if ($bucket->getAttribute('permission') === 'bucket') { $file = Authorization::skip(function() use ($dbForExternal, $fileId, $bucketId) { return $dbForExternal->getDocument('bucket_' . $bucketId, $fileId); }); @@ -1402,22 +1410,22 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view') $size = $file->getAttribute('sizeOriginal', 0); $rangeHeader = $request->getHeader('range'); - if(!empty($rangeHeader)) { + if (!empty($rangeHeader)) { $start = $request->getRangeStart(); $end = $request->getRangeEnd(); $unit = $request->getRangeUnit(); - if($end == null) { + if ($end === null) { $end = min(($start + 2000000-1), ($size - 1)); } - if($unit != 'bytes' || $start >= $end || $end >= $size) { + if ($unit != 'bytes' || $start >= $end || $end >= $size) { throw new Exception('Invalid range', 416); } $response ->addHeader('Accept-Ranges', 'bytes') - ->addHeader('Content-Range', 'bytes ' . $start . '-' . $end . '/' . $size) + ->addHeader('Content-Range', "bytes $start-$end/$size") ->addHeader('Content-Length', $end - $start + 1) ->setStatusCode(Response::STATUS_CODE_PARTIALCONTENT); } @@ -1436,7 +1444,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view') } if (!empty($file->getAttribute('algorithm', ''))) { - if(empty($source)) { + if (empty($source)) { $source = $device->read($path); } $compressor = new GZIP(); @@ -1448,23 +1456,29 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view') ->setParam('bucketId', $bucketId) ; - if(!empty($source)) { - if(!empty($rangeHeader)) { + if (!empty($source)) { + if (!empty($rangeHeader)) { $response->send(substr($source, $start, ($end - $start + 1))); } $response->send($source); } - if(!empty($rangeHeader)) { + if (!empty($rangeHeader)) { $response->send($device->read($path, $start, ($end - $start + 1))); } $size = $device->getFileSize($path); if ($size > APP_STORAGE_READ_BUFFER) { $response->addHeader('Content-Length', $device->getFileSize($path)); - $chunk = 2000000; // Max chunk of 2 mb - for ($i=0; $i < ceil($size / $chunk); $i++) { - $response->chunk($device->read($path, ($i * $chunk), min($chunk, $size - ($i * $chunk))), (($i + 1) * $chunk) >= $size); + for ($i=0; $i < ceil($size / MAX_OUTPUT_CHUNK_SIZE); $i++) { + $response->chunk( + $device->read( + $path, + ($i * MAX_OUTPUT_CHUNK_SIZE), + min(MAX_OUTPUT_CHUNK_SIZE, $size - ($i * MAX_OUTPUT_CHUNK_SIZE)) + ), + (($i + 1) * MAX_OUTPUT_CHUNK_SIZE) >= $size + ); } } else { $response->send($device->read($path)); @@ -1503,7 +1517,7 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId') $bucket = $dbForInternal->getDocument('buckets', $bucketId); - if($bucket->isEmpty() + if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN )) { throw new Exception('Bucket not found', 404); } @@ -1516,7 +1530,7 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId') } } - if($bucket->getAttribute('permission') === 'bucket') { + if ($bucket->getAttribute('permission') === 'bucket') { $file = Authorization::skip(function() use ($dbForExternal, $fileId, $bucketId) { return $dbForExternal->getDocument('bucket_' . $bucketId, $fileId); }); @@ -1528,7 +1542,7 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId') throw new Exception('File not found', 404); } - if($bucket->getAttribute('permission') === 'bucket') { + if ($bucket->getAttribute('permission') === 'bucket') { $file = Authorization::skip(function() use ($dbForExternal, $fileId, $bucketId, $file, $read, $write) { return $dbForExternal->updateDocument('bucket_' . $bucketId, $fileId, $file ->setAttribute('$read', $read) @@ -1587,7 +1601,7 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId') $bucket = $dbForInternal->getDocument('buckets', $bucketId); - if($bucket->isEmpty() + if ($bucket->isEmpty() || (!$bucket->getAttribute('enabled') && $mode !== APP_MODE_ADMIN )) { throw new Exception('Bucket not found', 404); } @@ -1600,7 +1614,7 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId') } } - if($bucket->getAttribute('permission') === 'bucket') { + if ($bucket->getAttribute('permission') === 'bucket') { $file = Authorization::skip(function() use ($dbForExternal, $fileId, $bucketId) { return $dbForExternal->getDocument('bucket_' . $bucketId, $fileId); }); @@ -1615,7 +1629,7 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId') $device = Storage::getDevice('files'); if ($device->delete($file->getAttribute('path', ''))) { - if($bucket->getAttribute('permission') === 'bucket') { + if ($bucket->getAttribute('permission') === 'bucket') { $deleted = Authorization::skip(function() use ($dbForExternal, $fileId, $bucketId) { return $dbForExternal->deleteDocument('bucket_' . $bucketId, $fileId); }); @@ -1778,7 +1792,7 @@ App::get('/v1/storage/:bucketId/usage') $bucket = $dbForInternal->getDocument('buckets', $bucketId); - if($bucket->isEmpty()) { + if ($bucket->isEmpty()) { throw new Exception('Bucket not found', 404); } diff --git a/composer.lock b/composer.lock index c1a91df291..1eaf8b75b7 100644 --- a/composer.lock +++ b/composer.lock @@ -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", @@ -2554,7 +2554,7 @@ "source": { "type": "git", "url": "https://github.com/utopia-php/storage", - "reference": "88ed83274542ba3c9d34c5dabd17e0cfb480519d" + "reference": "c47611b3a4a36c674c16e9720e86187452eb1cc2" }, "require": { "php": ">=8.0", @@ -2570,6 +2570,11 @@ "Utopia\\Storage\\": "src/Storage" } }, + "autoload-dev": { + "psr-4": { + "Utopia\\Tests\\": "tests/Storage" + } + }, "license": [ "MIT" ], @@ -2587,7 +2592,7 @@ "upf", "utopia" ], - "time": "2021-12-03T04:31:08+00:00" + "time": "2021-12-09T07:34:55+00:00" }, { "name": "utopia-php/swoole", @@ -3033,6 +3038,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", @@ -3116,25 +3192,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": { @@ -3160,7 +3238,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": [ { @@ -3176,7 +3254,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", @@ -4007,16 +4085,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": { @@ -4068,22 +4146,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": { @@ -4139,7 +4217,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": [ { @@ -4147,7 +4225,7 @@ "type": "github" } ], - "time": "2021-11-19T15:21:02+00:00" + "time": "2021-12-05T09:12:13+00:00" }, { "name": "phpunit/php-file-iterator",