diff --git a/appinfo/info.xml b/appinfo/info.xml index f2ede556..71624f2c 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -92,7 +92,7 @@ The app does not send any sensitive data to cloud providers or similar services. https://raw.githubusercontent.com/nextcloud/recognize/main/screenshots/Logo.png https://raw.githubusercontent.com/nextcloud/recognize/main/screenshots/imagenet_examples.jpg - + OCA\Recognize\BackgroundJobs\MaintenanceJob diff --git a/composer.json b/composer.json index 0c87f648..079e8289 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "require": { - "php": ">=8.0", + "php": ">=8.1", "ext-json": "*", "ext-pdo": "*", "rubix/ml": "2.x", @@ -13,8 +13,8 @@ }, "require-dev": { "nextcloud/ocp": "dev-master", - "symfony/console": "^5.4", - "symfony/process": "^5.2" + "symfony/console": "^6.4", + "symfony/process": "^6.4" }, "scripts": { "lint": "find . -name \\*.php -not -path './vendor/*' -print0 | xargs -0 -n1 php -l", @@ -37,7 +37,7 @@ }, "config": { "platform": { - "php": "8.0.2" + "php": "8.1.0" }, "allow-plugins": { "bamarni/composer-bin-plugin": true, diff --git a/lib/Hooks/FileListener.php b/lib/Hooks/FileListener.php index 54284016..459951c2 100644 --- a/lib/Hooks/FileListener.php +++ b/lib/Hooks/FileListener.php @@ -47,6 +47,7 @@ */ class FileListener implements IEventListener { private ?bool $movingFromIgnoredTerritory; + private ?array $movingDirFromIgnoredTerritory; /** @var list */ private array $sourceUserIds; private ?Node $source = null; @@ -64,6 +65,7 @@ public function __construct( private IJobList $jobList, ) { $this->movingFromIgnoredTerritory = null; + $this->movingDirFromIgnoredTerritory = null; $this->sourceUserIds = []; } @@ -139,16 +141,22 @@ public function handle(Event $event): void { } } if ($event instanceof BeforeNodeRenamedEvent) { + $this->movingFromIgnoredTerritory = null; + $this->movingDirFromIgnoredTerritory = []; if (in_array($event->getSource()->getName(), [...Constants::IGNORE_MARKERS_ALL, ...Constants::IGNORE_MARKERS_IMAGE, ...Constants::IGNORE_MARKERS_AUDIO, ...Constants::IGNORE_MARKERS_VIDEO], true)) { $this->resetIgnoreCache($event->getSource()); return; } // We try to remember whether the source node is in ignored territory // because after moving isIgnored doesn't work anymore :( - if ($this->isIgnored($event->getSource())) { - $this->movingFromIgnoredTerritory = true; + if ($event->getSource()->getType() !== FileInfo::TYPE_FOLDER) { + if ($this->isFileIgnored($event->getSource())) { + $this->movingFromIgnoredTerritory = true; + } else { + $this->movingFromIgnoredTerritory = false; + } } else { - $this->movingFromIgnoredTerritory = false; + $this->movingDirFromIgnoredTerritory = $this->getDirIgnores($event->getSource()); } $this->sourceUserIds = $this->getUsersWithFileAccess($event->getSource()); $this->source = $event->getSource(); @@ -175,23 +183,45 @@ public function handle(Event $event): void { $this->postDelete($event->getTarget()->getParent()); return; } - - if ($this->movingFromIgnoredTerritory) { - if ($this->isIgnored($event->getTarget())) { + if ($event->getTarget()->getType() !== FileInfo::TYPE_FOLDER) { + if ($this->movingFromIgnoredTerritory) { + if ($this->isFileIgnored($event->getTarget())) { + return; + } + $this->postInsert($event->getTarget()); + return; + } + if ($this->isFileIgnored($event->getTarget())) { + $this->postDelete($event->getTarget()); + return; + } + } else { + if ($this->movingDirFromIgnoredTerritory !== null && count($this->movingDirFromIgnoredTerritory) !== 0) { + $oldIgnores = $this->movingDirFromIgnoredTerritory; + $newIgnores = $this->getDirIgnores($event->getTarget()); + $diff1 = array_diff($newIgnores, $oldIgnores); + $diff2 = array_diff($oldIgnores, $newIgnores); + if (count($diff1) !== 0 || count($diff2) !== 0) { + if (count($diff1) !== 0) { + $this->postDelete($event->getTarget(), true, $diff1); + } + if (count($diff2) !== 0) { + $this->postInsert($event->getTarget(), true, $diff2); + } + } + return; + } + $ignoredMimeTypes = $this->getDirIgnores($event->getTarget()); + if (!empty($ignoredMimeTypes)) { + $this->postDelete($event->getTarget(), true, $ignoredMimeTypes); return; } - $this->postInsert($event->getTarget()); - return; - } - if ($this->isIgnored($event->getTarget())) { - $this->postDelete($event->getTarget()); - return; } $this->postRename($this->source ?? $event->getSource(), $event->getTarget()); return; } if ($event instanceof BeforeNodeDeletedEvent) { - $this->postDelete($event->getNode(), false); + $this->postDelete($event->getNode()); return; } if ($event instanceof NodeDeletedEvent) { @@ -246,7 +276,7 @@ public function handle(Event $event): void { } } - public function postDelete(Node $node, bool $recurse = true): void { + public function postDelete(Node $node, bool $recurse = true, ?array $mimeTypes = null): void { if ($node->getType() === FileInfo::TYPE_FOLDER) { if (!$recurse) { return; @@ -254,7 +284,7 @@ public function postDelete(Node $node, bool $recurse = true): void { try { /** @var Folder $node */ foreach ($node->getDirectoryListing() as $child) { - $this->postDelete($child); + $this->postDelete($child, true, $mimeTypes); } } catch (NotFoundException $e) { $this->logger->debug($e->getMessage(), ['exception' => $e]); @@ -262,6 +292,10 @@ public function postDelete(Node $node, bool $recurse = true): void { return; } + if ($mimeTypes !== null && !in_array($node->getMimetype(), $mimeTypes)) { + return; + } + // Try Deleting possibly existing face detections try { /** @@ -291,7 +325,7 @@ public function postDelete(Node $node, bool $recurse = true): void { /** * @throws \OCP\Files\InvalidPathException */ - public function postInsert(Node $node, bool $recurse = true): void { + public function postInsert(Node $node, bool $recurse = true, ?array $mimeTypes = null): void { if ($node->getType() === FileInfo::TYPE_FOLDER) { if (!$recurse) { return; @@ -309,6 +343,10 @@ public function postInsert(Node $node, bool $recurse = true): void { return; } + if ($mimeTypes !== null && !in_array($node->getMimetype(), $mimeTypes)) { + return; + } + $queueFile = new QueueFile(); if ($node->getMountPoint()->getNumericStorageId() === null) { return; @@ -316,7 +354,7 @@ public function postInsert(Node $node, bool $recurse = true): void { $queueFile->setStorageId($node->getMountPoint()->getNumericStorageId()); $queueFile->setRootId($node->getMountPoint()->getStorageRootId()); - if ($this->isIgnored($node)) { + if ($this->isFileIgnored($node)) { return; } @@ -401,7 +439,7 @@ private function copyFaceDetectionsForNode(string $ownerId, array $usersToAdd, a * @throws \OCP\Files\InvalidPathException * @throws \OCP\Files\NotFoundException */ - public function isIgnored(Node $node) : bool { + public function isFileIgnored(Node $node) : bool { $ignoreMarkers = []; $mimeType = $node->getMimetype(); $storageId = $node->getMountPoint()->getNumericStorageId(); @@ -419,6 +457,7 @@ public function isIgnored(Node $node) : bool { if (in_array($mimeType, Constants::AUDIO_FORMATS)) { $ignoreMarkers = array_merge($ignoreMarkers, Constants::IGNORE_MARKERS_AUDIO); } + if (count($ignoreMarkers) === 0) { return true; } @@ -426,17 +465,45 @@ public function isIgnored(Node $node) : bool { $ignoreMarkers = array_merge($ignoreMarkers, Constants::IGNORE_MARKERS_ALL); $ignoredPaths = $this->ignoreService->getIgnoredDirectories($storageId, $ignoreMarkers); - $relevantIgnorePaths = array_filter($ignoredPaths, static function (string $ignoredPath) use ($node) { - return stripos($node->getInternalPath(), $ignoredPath ? $ignoredPath . '/' : $ignoredPath) === 0; - }); - if (count($relevantIgnorePaths) > 0) { - return true; + foreach ($ignoredPaths as $ignoredPath) { + if (stripos($node->getInternalPath(), $ignoredPath ? $ignoredPath . '/' : $ignoredPath) === 0) { + return true; + } } - return false; } + /** + * @param \OCP\Files\Node $node + * @return array + * @throws Exception + */ + public function getDirIgnores(Node $node) : array { + $storageId = $node->getMountPoint()->getNumericStorageId(); + if ($storageId === null) { + return []; + } + + $ignoredMimeTypes = []; + foreach ([ + [Constants::IGNORE_MARKERS_IMAGE, Constants::IMAGE_FORMATS], + [Constants::IGNORE_MARKERS_VIDEO, Constants::VIDEO_FORMATS], + [Constants::IGNORE_MARKERS_AUDIO, Constants::AUDIO_FORMATS], + [Constants::IGNORE_MARKERS_ALL, array_merge(Constants::IMAGE_FORMATS, Constants::VIDEO_FORMATS, Constants::AUDIO_FORMATS)], + ] as $iteration) { + [$ignoreMarkers, $mimeTypes] = $iteration; + $ignoredPaths = $this->ignoreService->getIgnoredDirectories($storageId, $ignoreMarkers); + foreach ($ignoredPaths as $ignoredPath) { + if (stripos($node->getInternalPath(), $ignoredPath ? $ignoredPath . '/' : $ignoredPath) === 0) { + $ignoredMimeTypes = array_unique(array_merge($ignoredMimeTypes, $mimeTypes)); + } + } + } + + return $ignoredMimeTypes; + } + private function resetIgnoreCache(Node $node) : void { $storageId = $node->getMountPoint()->getNumericStorageId(); if ($storageId === null) { diff --git a/lib/Service/Logger.php b/lib/Service/Logger.php index 1346beb7..a2ffeb3e 100644 --- a/lib/Service/Logger.php +++ b/lib/Service/Logger.php @@ -8,6 +8,7 @@ use Psr\Log\LoggerInterface; use Symfony\Component\Console\Output\OutputInterface; +use \Stringable; class Logger implements LoggerInterface { private LoggerInterface $logger; @@ -30,7 +31,7 @@ public function setCliOutput(OutputInterface $out): Logger { /** * @inheritDoc */ - public function emergency($message, array $context = array()) { + public function emergency(Stringable|string $message, array $context = array()): void { if (isset($this->cliOutput)) { $this->cliOutput->writeln($message); } @@ -40,7 +41,7 @@ public function emergency($message, array $context = array()) { /** * @inheritDoc */ - public function alert($message, array $context = array()) { + public function alert(Stringable|string $message, array $context = array()): void { if (isset($this->cliOutput)) { $this->cliOutput->writeln($message); } @@ -50,7 +51,7 @@ public function alert($message, array $context = array()) { /** * @inheritDoc */ - public function critical($message, array $context = array()) { + public function critical(Stringable|string $message, array $context = array()): void { if (isset($this->cliOutput)) { $this->cliOutput->writeln($message); } @@ -60,7 +61,7 @@ public function critical($message, array $context = array()) { /** * @inheritDoc */ - public function error($message, array $context = array()) { + public function error(Stringable|string $message, array $context = array()): void { if (isset($this->cliOutput)) { $this->cliOutput->writeln($message); } @@ -70,7 +71,7 @@ public function error($message, array $context = array()) { /** * @inheritDoc */ - public function warning($message, array $context = array()) { + public function warning(Stringable|string $message, array $context = array()): void { if (isset($this->cliOutput)) { $this->cliOutput->writeln($message); } @@ -80,7 +81,7 @@ public function warning($message, array $context = array()) { /** * @inheritDoc */ - public function notice($message, array $context = array()) { + public function notice(Stringable|string $message, array $context = array()): void { if (isset($this->cliOutput)) { $this->cliOutput->writeln($message); } @@ -90,7 +91,7 @@ public function notice($message, array $context = array()) { /** * @inheritDoc */ - public function info($message, array $context = array()) { + public function info(Stringable|string $message, array $context = array()): void { if (isset($this->cliOutput) && !$this->cliOutput->isQuiet()) { $this->cliOutput->writeln($message); } @@ -100,7 +101,7 @@ public function info($message, array $context = array()) { /** * @inheritDoc */ - public function debug($message, array $context = array()) { + public function debug(Stringable|string $message, array $context = array()): void { if (isset($this->cliOutput) && !$this->cliOutput->isQuiet()) { $this->cliOutput->writeln($message); } @@ -110,7 +111,7 @@ public function debug($message, array $context = array()) { /** * @inheritDoc */ - public function log($level, $message, array $context = array()) { + public function log($level, Stringable|string $message, array $context = array()): void { if (isset($this->cliOutput)) { $this->cliOutput->writeln($message); } diff --git a/tests/ClassifierTest.php b/tests/ClassifierTest.php index 94aa5482..72c65ba5 100644 --- a/tests/ClassifierTest.php +++ b/tests/ClassifierTest.php @@ -184,6 +184,59 @@ public function testFileListener(string $ignoreFileName) : void { self::assertCount(0, $this->queue->getFromQueue(ImagenetClassifier::MODEL_NAME, $storageId, $rootId, 100), 'entry should have been removed from imagenet queue after moving it into ignored territory'); } + /** + * @dataProvider ignoreImageFilesProvider + * @return void + * @throws \OCP\DB\Exception + * @throws \OCP\Files\InvalidPathException + * @throws \OCP\Files\NotFoundException + * @throws \OCP\Files\NotPermittedException + */ + public function testFileListenerWithFolder(string $ignoreFileName) : void { + $this->config->setAppValueString('imagenet.enabled', 'true'); + $this->queue->clearQueue(ImagenetClassifier::MODEL_NAME); + + $folder = $this->userFolder->newFolder('/folder/'); + $this->testFile = $folder->newFile('/alpine.jpg', file_get_contents(__DIR__.'/res/alpine.JPG')); + $ignoreFolder = $this->userFolder->newFolder('/test/ignore/'); + $ignoredFolder = $ignoreFolder->newFolder('/folder/'); + $ignoreFile = $this->userFolder->newFile('/test/' . $ignoreFileName, ''); + $this->ignoredFile = $ignoredFolder->newFile('/alpine-2.jpg', file_get_contents(__DIR__.'/res/alpine.JPG')); + + $storageId = $this->testFile->getMountPoint()->getNumericStorageId(); + $rootId = $this->testFile->getMountPoint()->getStorageRootId(); + + self::assertCount(1, $this->queue->getFromQueue(ImagenetClassifier::MODEL_NAME, $storageId, $rootId, 100), 'one element should have been added to imagenet queue'); + + $folder->delete(); + + self::assertCount(0, $this->queue->getFromQueue(ImagenetClassifier::MODEL_NAME, $storageId, $rootId, 100), 'entry should have been removed from imagenet queue'); + + $ignoreFile->delete(); + + self::assertCount(1, $this->queue->getFromQueue(ImagenetClassifier::MODEL_NAME, $storageId, $rootId, 100), 'one element should have been added to imagenet queue after deleting ignore file'); + + $ignoreFile = $this->userFolder->newFile('/test/' . $ignoreFileName, ''); + + self::assertCount(0, $this->queue->getFromQueue(ImagenetClassifier::MODEL_NAME, $storageId, $rootId, 100), 'entry should have been removed from imagenet queue after creating ignore file'); + + $ignoredFolder->move($this->userFolder->getPath() . '/folder2'); + + self::assertCount(1, $this->queue->getFromQueue(ImagenetClassifier::MODEL_NAME, $storageId, $rootId, 100), 'one element should have been added to imagenet queue after moving it out of ignored territory'); + + $ignoreFile->move($this->userFolder->getPath() . '/' . $ignoreFileName); + + self::assertCount(0, $this->queue->getFromQueue(ImagenetClassifier::MODEL_NAME, $storageId, $rootId, 100), 'entry should have been removed from imagenet queue after moving ignore file'); + + $ignoreFile->move($this->userFolder->getPath() . '/test/' . $ignoreFileName); + + self::assertCount(1, $this->queue->getFromQueue(ImagenetClassifier::MODEL_NAME, $storageId, $rootId, 100), 'one element should have been added to imagenet queue after moving ignore file'); + + $ignoredFolder->move($this->userFolder->getPath() . '/test/ignore/folder'); + + self::assertCount(0, $this->queue->getFromQueue(ImagenetClassifier::MODEL_NAME, $storageId, $rootId, 100), 'entry should have been removed from imagenet queue after moving it into ignored territory'); + } + /** * @dataProvider ignoreImageFilesProvider * @return void diff --git a/vendor-bin/php-scoper/composer.lock b/vendor-bin/php-scoper/composer.lock index d54df316..de81ac68 100644 --- a/vendor-bin/php-scoper/composer.lock +++ b/vendor-bin/php-scoper/composer.lock @@ -9,44 +9,45 @@ "packages-dev": [ { "name": "fidry/console", - "version": "0.5.5", + "version": "0.6.10", "source": { "type": "git", "url": "https://github.com/theofidry/console.git", - "reference": "bc1fe03f600c63f12ec0a39c6b746c1a1fb77bf7" + "reference": "a681ea3aa7f5c0c78cd437250f64b13d2818c95d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theofidry/console/zipball/bc1fe03f600c63f12ec0a39c6b746c1a1fb77bf7", - "reference": "bc1fe03f600c63f12ec0a39c6b746c1a1fb77bf7", + "url": "https://api.github.com/repos/theofidry/console/zipball/a681ea3aa7f5c0c78cd437250f64b13d2818c95d", + "reference": "a681ea3aa7f5c0c78cd437250f64b13d2818c95d", "shasum": "" }, "require": { - "php": "^7.4.0 || ^8.0.0", - "symfony/console": "^4.4 || ^5.4 || ^6.1", - "symfony/event-dispatcher-contracts": "^1.0 || ^2.5 || ^3.0", - "symfony/service-contracts": "^1.0 || ^2.5 || ^3.0", - "thecodingmachine/safe": "^1.3 || ^2.0", + "php": "^8.2", + "psr/log": "^3.0", + "symfony/console": "^6.4 || ^7.0", + "symfony/deprecation-contracts": "^3.4", + "symfony/event-dispatcher-contracts": "^2.5 || ^3.0", + "symfony/service-contracts": "^2.5 || ^3.0", + "thecodingmachine/safe": "^2.0", "webmozart/assert": "^1.11" }, "conflict": { - "symfony/dependency-injection": "<5.3.0", - "symfony/framework-bundle": "<5.3.0", - "symfony/http-kernel": "<5.3.0" + "symfony/dependency-injection": "<6.4.0", + "symfony/framework-bundle": "<6.4.0", + "symfony/http-kernel": "<6.4.0" }, "require-dev": { - "bamarni/composer-bin-plugin": "^1.4", - "composer/semver": "^3.3", - "ergebnis/composer-normalize": "^2.28", - "infection/infection": "^0.26", - "phpspec/prophecy-phpunit": "^2.0", - "phpunit/phpunit": "^9.4.3", - "symfony/dependency-injection": "^4.4 || ^5.4 || ^6.1", - "symfony/framework-bundle": "^4.4 || ^5.4 || ^6.1", - "symfony/http-kernel": "^4.4 || ^5.4 || ^6.1", - "symfony/phpunit-bridge": "^4.4.47 || ^5.4 || ^6.0", - "symfony/yaml": "^4.4 || ^5.4 || ^6.1", - "webmozarts/strict-phpunit": "^7.3" + "bamarni/composer-bin-plugin": "^1.8.2", + "composer/semver": "^3.3.2", + "ergebnis/composer-normalize": "^2.33", + "fidry/makefile": "^0.2.1 || ^1.0.0", + "infection/infection": "^0.28", + "phpunit/phpunit": "^10.2", + "symfony/dependency-injection": "^6.4", + "symfony/flex": "^2.4.0", + "symfony/framework-bundle": "^6.4", + "symfony/http-kernel": "^6.4", + "symfony/yaml": "^6.4 || ^7.0" }, "type": "library", "extra": { @@ -81,7 +82,7 @@ ], "support": { "issues": "https://github.com/theofidry/console/issues", - "source": "https://github.com/theofidry/console/tree/0.5.5" + "source": "https://github.com/theofidry/console/tree/0.6.10" }, "funding": [ { @@ -89,7 +90,7 @@ "type": "github" } ], - "time": "2022-12-18T10:49:34+00:00" + "time": "2024-04-23T08:36:33+00:00" }, { "name": "fidry/filesystem", @@ -160,37 +161,38 @@ }, { "name": "humbug/php-scoper", - "version": "0.18.7", + "version": "0.18.15", "source": { "type": "git", "url": "https://github.com/humbug/php-scoper.git", - "reference": "9386a0af946f175d7a1ebfb68851bc2bb8ad7858" + "reference": "79b2b4e0fbc1d1ef6ae99c4e078137b42bd43d19" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/humbug/php-scoper/zipball/9386a0af946f175d7a1ebfb68851bc2bb8ad7858", - "reference": "9386a0af946f175d7a1ebfb68851bc2bb8ad7858", + "url": "https://api.github.com/repos/humbug/php-scoper/zipball/79b2b4e0fbc1d1ef6ae99c4e078137b42bd43d19", + "reference": "79b2b4e0fbc1d1ef6ae99c4e078137b42bd43d19", "shasum": "" }, "require": { - "fidry/console": "^0.5.0", + "fidry/console": "^0.6.10", "fidry/filesystem": "^1.1", - "jetbrains/phpstorm-stubs": "^v2022.2", - "nikic/php-parser": "^4.12", - "php": "^8.1", - "symfony/console": "^5.2 || ^6.0", - "symfony/filesystem": "^5.2 || ^6.0", - "symfony/finder": "^5.2 || ^6.0", + "jetbrains/phpstorm-stubs": "^2024.1", + "nikic/php-parser": "^5.0", + "php": "^8.2", + "symfony/console": "^6.4 || ^7.0", + "symfony/filesystem": "^6.4 || ^7.0", + "symfony/finder": "^6.4 || ^7.0", + "symfony/var-dumper": "^7.1", "thecodingmachine/safe": "^2.0" }, "require-dev": { "bamarni/composer-bin-plugin": "^1.1", "ergebnis/composer-normalize": "^2.28", "fidry/makefile": "^1.0", - "humbug/box": "^4.5.1", + "humbug/box": "^4.6.2", "phpspec/prophecy-phpunit": "^2.0", - "phpunit/phpunit": "^9.0", - "symfony/yaml": "^6.1" + "phpunit/phpunit": "^10.0", + "symfony/yaml": "^6.4 || ^7.0" }, "bin": [ "bin/php-scoper" @@ -237,30 +239,29 @@ "description": "Prefixes all PHP namespaces in a file or directory.", "support": { "issues": "https://github.com/humbug/php-scoper/issues", - "source": "https://github.com/humbug/php-scoper/tree/0.18.7" + "source": "https://github.com/humbug/php-scoper/tree/0.18.15" }, - "time": "2023-11-04T18:01:12+00:00" + "time": "2024-09-02T13:35:10+00:00" }, { "name": "jetbrains/phpstorm-stubs", - "version": "v2022.3", + "version": "v2024.2", "source": { "type": "git", "url": "https://github.com/JetBrains/phpstorm-stubs.git", - "reference": "6b568c153cea002dc6fad96285c3063d07cab18d" + "reference": "cf7e447ddfa7f0cbab0c1dd38392f0cb05f9881c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/JetBrains/phpstorm-stubs/zipball/6b568c153cea002dc6fad96285c3063d07cab18d", - "reference": "6b568c153cea002dc6fad96285c3063d07cab18d", + "url": "https://api.github.com/repos/JetBrains/phpstorm-stubs/zipball/cf7e447ddfa7f0cbab0c1dd38392f0cb05f9881c", + "reference": "cf7e447ddfa7f0cbab0c1dd38392f0cb05f9881c", "shasum": "" }, "require-dev": { - "friendsofphp/php-cs-fixer": "@stable", - "nikic/php-parser": "@stable", - "php": "^8.0", - "phpdocumentor/reflection-docblock": "@stable", - "phpunit/phpunit": "@stable" + "friendsofphp/php-cs-fixer": "v3.46.0", + "nikic/php-parser": "v5.0.0", + "phpdocumentor/reflection-docblock": "5.3.0", + "phpunit/phpunit": "10.5.5" }, "type": "library", "autoload": { @@ -285,31 +286,33 @@ "type" ], "support": { - "source": "https://github.com/JetBrains/phpstorm-stubs/tree/v2022.3" + "source": "https://github.com/JetBrains/phpstorm-stubs/tree/v2024.2" }, - "time": "2022-10-17T09:21:37+00:00" + "time": "2024-06-17T19:18:18+00:00" }, { "name": "nikic/php-parser", - "version": "v4.19.1", + "version": "v5.3.1", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "4e1b88d21c69391150ace211e9eaf05810858d0b" + "reference": "8eea230464783aa9671db8eea6f8c6ac5285794b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/4e1b88d21c69391150ace211e9eaf05810858d0b", - "reference": "4e1b88d21c69391150ace211e9eaf05810858d0b", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/8eea230464783aa9671db8eea6f8c6ac5285794b", + "reference": "8eea230464783aa9671db8eea6f8c6ac5285794b", "shasum": "" }, "require": { + "ext-ctype": "*", + "ext-json": "*", "ext-tokenizer": "*", - "php": ">=7.1" + "php": ">=7.4" }, "require-dev": { "ircmaxell/php-yacc": "^0.0.7", - "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" + "phpunit/phpunit": "^9.0" }, "bin": [ "bin/php-parse" @@ -317,7 +320,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "4.9-dev" + "dev-master": "5.0-dev" } }, "autoload": { @@ -341,9 +344,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.19.1" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.3.1" }, - "time": "2024-03-17T08:10:35+00:00" + "time": "2024-10-08T18:51:32+00:00" }, { "name": "psr/container", @@ -448,49 +451,98 @@ }, "time": "2019-01-08T18:20:26+00:00" }, + { + "name": "psr/log", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/3.0.2" + }, + "time": "2024-09-11T13:17:53+00:00" + }, { "name": "symfony/console", - "version": "v6.4.11", + "version": "v7.1.5", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "42686880adaacdad1835ee8fc2a9ec5b7bd63998" + "reference": "0fa539d12b3ccf068a722bbbffa07ca7079af9ee" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/42686880adaacdad1835ee8fc2a9ec5b7bd63998", - "reference": "42686880adaacdad1835ee8fc2a9ec5b7bd63998", + "url": "https://api.github.com/repos/symfony/console/zipball/0fa539d12b3ccf068a722bbbffa07ca7079af9ee", + "reference": "0fa539d12b3ccf068a722bbbffa07ca7079af9ee", "shasum": "" }, "require": { - "php": ">=8.1", - "symfony/deprecation-contracts": "^2.5|^3", + "php": ">=8.2", "symfony/polyfill-mbstring": "~1.0", "symfony/service-contracts": "^2.5|^3", - "symfony/string": "^5.4|^6.0|^7.0" + "symfony/string": "^6.4|^7.0" }, "conflict": { - "symfony/dependency-injection": "<5.4", - "symfony/dotenv": "<5.4", - "symfony/event-dispatcher": "<5.4", - "symfony/lock": "<5.4", - "symfony/process": "<5.4" + "symfony/dependency-injection": "<6.4", + "symfony/dotenv": "<6.4", + "symfony/event-dispatcher": "<6.4", + "symfony/lock": "<6.4", + "symfony/process": "<6.4" }, "provide": { "psr/log-implementation": "1.0|2.0|3.0" }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0|^7.0", - "symfony/dependency-injection": "^5.4|^6.0|^7.0", - "symfony/event-dispatcher": "^5.4|^6.0|^7.0", + "symfony/config": "^6.4|^7.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/event-dispatcher": "^6.4|^7.0", "symfony/http-foundation": "^6.4|^7.0", "symfony/http-kernel": "^6.4|^7.0", - "symfony/lock": "^5.4|^6.0|^7.0", - "symfony/messenger": "^5.4|^6.0|^7.0", - "symfony/process": "^5.4|^6.0|^7.0", - "symfony/stopwatch": "^5.4|^6.0|^7.0", - "symfony/var-dumper": "^5.4|^6.0|^7.0" + "symfony/lock": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/stopwatch": "^6.4|^7.0", + "symfony/var-dumper": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -524,7 +576,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.4.11" + "source": "https://github.com/symfony/console/tree/v7.1.5" }, "funding": [ { @@ -540,7 +592,7 @@ "type": "tidelift" } ], - "time": "2024-08-15T22:48:29+00:00" + "time": "2024-09-20T08:28:38+00:00" }, { "name": "symfony/deprecation-contracts", @@ -687,25 +739,25 @@ }, { "name": "symfony/filesystem", - "version": "v6.4.9", + "version": "v7.1.5", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "b51ef8059159330b74a4d52f68e671033c0fe463" + "reference": "61fe0566189bf32e8cfee78335d8776f64a66f5a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/b51ef8059159330b74a4d52f68e671033c0fe463", - "reference": "b51ef8059159330b74a4d52f68e671033c0fe463", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/61fe0566189bf32e8cfee78335d8776f64a66f5a", + "reference": "61fe0566189bf32e8cfee78335d8776f64a66f5a", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.8" }, "require-dev": { - "symfony/process": "^5.4|^6.4|^7.0" + "symfony/process": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -733,7 +785,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v6.4.9" + "source": "https://github.com/symfony/filesystem/tree/v7.1.5" }, "funding": [ { @@ -749,27 +801,27 @@ "type": "tidelift" } ], - "time": "2024-06-28T09:49:33+00:00" + "time": "2024-09-17T09:16:35+00:00" }, { "name": "symfony/finder", - "version": "v6.4.11", + "version": "v7.1.4", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "d7eb6daf8cd7e9ac4976e9576b32042ef7253453" + "reference": "d95bbf319f7d052082fb7af147e0f835a695e823" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/d7eb6daf8cd7e9ac4976e9576b32042ef7253453", - "reference": "d7eb6daf8cd7e9ac4976e9576b32042ef7253453", + "url": "https://api.github.com/repos/symfony/finder/zipball/d95bbf319f7d052082fb7af147e0f835a695e823", + "reference": "d95bbf319f7d052082fb7af147e0f835a695e823", "shasum": "" }, "require": { - "php": ">=8.1" + "php": ">=8.2" }, "require-dev": { - "symfony/filesystem": "^6.0|^7.0" + "symfony/filesystem": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -797,7 +849,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v6.4.11" + "source": "https://github.com/symfony/finder/tree/v7.1.4" }, "funding": [ { @@ -813,7 +865,7 @@ "type": "tidelift" } ], - "time": "2024-08-13T14:27:37+00:00" + "time": "2024-08-13T14:28:19+00:00" }, { "name": "symfony/polyfill-ctype", @@ -1218,20 +1270,20 @@ }, { "name": "symfony/string", - "version": "v6.4.11", + "version": "v7.1.5", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "5bc3eb632cf9c8dbfd6529d89be9950d1518883b" + "reference": "d66f9c343fa894ec2037cc928381df90a7ad4306" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/5bc3eb632cf9c8dbfd6529d89be9950d1518883b", - "reference": "5bc3eb632cf9c8dbfd6529d89be9950d1518883b", + "url": "https://api.github.com/repos/symfony/string/zipball/d66f9c343fa894ec2037cc928381df90a7ad4306", + "reference": "d66f9c343fa894ec2037cc928381df90a7ad4306", "shasum": "" }, "require": { - "php": ">=8.1", + "php": ">=8.2", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-intl-grapheme": "~1.0", "symfony/polyfill-intl-normalizer": "~1.0", @@ -1241,11 +1293,12 @@ "symfony/translation-contracts": "<2.5" }, "require-dev": { - "symfony/error-handler": "^5.4|^6.0|^7.0", - "symfony/http-client": "^5.4|^6.0|^7.0", - "symfony/intl": "^6.2|^7.0", + "symfony/emoji": "^7.1", + "symfony/error-handler": "^6.4|^7.0", + "symfony/http-client": "^6.4|^7.0", + "symfony/intl": "^6.4|^7.0", "symfony/translation-contracts": "^2.5|^3.0", - "symfony/var-exporter": "^5.4|^6.0|^7.0" + "symfony/var-exporter": "^6.4|^7.0" }, "type": "library", "autoload": { @@ -1284,7 +1337,90 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.4.11" + "source": "https://github.com/symfony/string/tree/v7.1.5" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-20T08:28:38+00:00" + }, + { + "name": "symfony/var-dumper", + "version": "v7.1.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-dumper.git", + "reference": "e20e03889539fd4e4211e14d2179226c513c010d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/e20e03889539fd4e4211e14d2179226c513c010d", + "reference": "e20e03889539fd4e4211e14d2179226c513c010d", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/console": "<6.4" + }, + "require-dev": { + "ext-iconv": "*", + "symfony/console": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/uid": "^6.4|^7.0", + "twig/twig": "^3.0.4" + }, + "bin": [ + "Resources/bin/var-dump-server" + ], + "type": "library", + "autoload": { + "files": [ + "Resources/functions/dump.php" + ], + "psr-4": { + "Symfony\\Component\\VarDumper\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides mechanisms for walking through any arbitrary PHP variable", + "homepage": "https://symfony.com", + "keywords": [ + "debug", + "dump" + ], + "support": { + "source": "https://github.com/symfony/var-dumper/tree/v7.1.5" }, "funding": [ { @@ -1300,7 +1436,7 @@ "type": "tidelift" } ], - "time": "2024-08-12T09:55:28+00:00" + "time": "2024-09-16T10:07:02+00:00" }, { "name": "thecodingmachine/safe", @@ -1507,5 +1643,5 @@ "prefer-lowest": false, "platform": [], "platform-dev": [], - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.6.0" }