From 23f00b2374b3e82a5c2fd87d19c6dad9dd920051 Mon Sep 17 00:00:00 2001 From: Lukas Rosenstock Date: Tue, 26 May 2026 15:38:15 +0000 Subject: [PATCH] Remove outdated doctrine/cache package and change configuration --- .../InvalidSDKConfigurationException.php | 14 + CloudObjects/SDK/ObjectRetriever.php | 94 ++-- .../SDK/TestHelpers/InMemoryLogger.php | 63 +++ README.md | 59 +- composer.json | 6 +- composer.lock | 530 ++++-------------- .../OnlineTests/ObjectRetrieverCacheTest.php | 47 ++ 7 files changed, 295 insertions(+), 518 deletions(-) create mode 100644 CloudObjects/SDK/Exceptions/InvalidSDKConfigurationException.php create mode 100644 CloudObjects/SDK/TestHelpers/InMemoryLogger.php create mode 100644 tests/OnlineTests/ObjectRetrieverCacheTest.php diff --git a/CloudObjects/SDK/Exceptions/InvalidSDKConfigurationException.php b/CloudObjects/SDK/Exceptions/InvalidSDKConfigurationException.php new file mode 100644 index 0000000..50745e0 --- /dev/null +++ b/CloudObjects/SDK/Exceptions/InvalidSDKConfigurationException.php @@ -0,0 +1,14 @@ +options = array_merge([ - 'cache_provider' => 'none', + 'cache_storage' => null, 'cache_prefix' => 'clobj:', 'cache_ttl' => 60, 'static_config_path' => null, @@ -48,35 +57,27 @@ class ObjectRetriever implements CustomCacheAndLogInterface { 'connect_timeout' => 5 ], $options); - // Set up object cache - switch ($this->options['cache_provider']) { - case 'none': - // no caching - $this->cache = null; - break; - case 'redis': - // caching with Redis - $redis = new \Redis(); - $redis->pconnect( - isset($this->options['cache_provider.redis.host']) ? $this->options['cache_provider.redis.host'] : '127.0.0.1', - isset($this->options['cache_provider.redis.port']) ? $this->options['cache_provider.redis.port'] : 6379); + // Check object cache configuration + if (isset($this->options['cache_storage']) + && !($this->options['cache_storage'] instanceof CacheStorageInterface) + && !($this->options['cache_storage'] instanceof CacheItemPoolInterface) + && !($this->options['cache_storage'] instanceof CacheInterface) + ) { + throw new InvalidSDKConfigurationException('Invalid cache_storage specified; must be an instance of Kevinrob\GuzzleCache\CacheStorageInterface, Psr\Cache\CacheItemPoolInterface or Psr\SimpleCache\CacheInterface.'); + } - $this->cache = new RedisCache(); - $this->cache->setRedis($redis); - break; - case 'file': - // caching on the filesystem - $this->cache = new \Doctrine\Common\Cache\FilesystemCache( - isset($this->options['cache_provider.file.directory']) ? $this->options['cache_provider.file.directory'] : sys_get_temp_dir() - ); - break; - default: - throw new Exception('Valid values for cache_provider are: none, redis, file'); + if ($this->options['cache_storage'] instanceof CacheStorageInterface) { + $this->cache = $this->options['cache_storage']; + } elseif ($this->options['cache_storage'] instanceof CacheItemPoolInterface) { + $this->cache = new Psr6CacheStorage($this->options['cache_storage']); + } elseif ($this->options['cache_storage'] instanceof CacheInterface) { + $this->cache = new Psr16CacheStorage($this->options['cache_storage']); } // Set up logger - if (is_a($this->options['logger'], LoggerInterface::class)) + if (is_a($this->options['logger'], LoggerInterface::class)) { $this->setLogger($this->options['logger']); + } // Set up handler stack $stack = HandlerStack::create(); @@ -85,11 +86,14 @@ class ObjectRetriever implements CustomCacheAndLogInterface { if (isset($this->cache)) { $stack->push( new CacheMiddleware( - new PrivateCacheStrategy( - new DoctrineCacheStorage($this->cache) - ) + new PrivateCacheStrategy($this->cache) ) ); + + // We also use the cache for storing object descriptions and attachments + // without the HTTP request, so we create a dummy request; this way + // we can reuse GuzzleCache for maximum compatibility + $this->customCacheDefaultRequest = new Request('GET', '/'); } // Initialize client @@ -127,18 +131,32 @@ class ObjectRetriever implements CustomCacheAndLogInterface { $this->logger->info($message, [ 'elapsed_ms' => round((microtime(true) - $ts) * 1000) ]); } - private function getCacheKey($id) { - return $this->options['cache_prefix'].$this->options['auth_ns'].'/'.$id; + public function getCacheKey($id) { + return $this->options['cache_prefix'] . $this->options['auth_ns'] . '/' . $id; } private function getFromCache($id) { - return (isset($this->cache) && $this->cache->contains($this->getCacheKey($id))) - ? $this->cache->fetch($this->getCacheKey($id)) : null; + if (!$this->cache) { + return null; + } + + $cachedData = $this->cache->fetch($this->getCacheKey($id)); + + if (!$cachedData) { + return null; + } + + return $cachedData->getOriginalResponse()->getBody()->getContents(); } private function putIntoCache($id, $data, $ttl) { - if (isset($this->cache)) - $this->cache->save($this->getCacheKey($id), $data, $ttl); + if ($this->cache) { + $entry = new CacheEntry($this->customCacheDefaultRequest, + new Response(200, [], $data), + ((new DateTime)->modify('+'.$ttl.' seconds'))); + + $this->cache->save($this->getCacheKey($id), $entry, $ttl); + } } public function getFromCacheCustom($id) { diff --git a/CloudObjects/SDK/TestHelpers/InMemoryLogger.php b/CloudObjects/SDK/TestHelpers/InMemoryLogger.php new file mode 100644 index 0000000..8594c7e --- /dev/null +++ b/CloudObjects/SDK/TestHelpers/InMemoryLogger.php @@ -0,0 +1,63 @@ +logs; + } + + public function getLastLogMessage() : string { + if (empty($this->logs)) { + return ''; + } + + return end($this->logs)['message']; + } + + public function emergency(string|\Stringable $message, array $context = []): void { + $this->logs[] = [ 'level' => 'emergency', 'message' => (string)$message, 'context' => $context ]; + } + + public function alert(string|\Stringable $message, array $context = []): void { + $this->logs[] = [ 'level' => 'alert', 'message' => (string)$message, 'context' => $context ]; + } + + public function critical(string|\Stringable $message, array $context = []): void { + $this->logs[] = [ 'level' => 'critical', 'message' => (string)$message, 'context' => $context ]; + } + + public function error(string|\Stringable $message, array $context = []): void { + $this->logs[] = [ 'level' => 'error', 'message' => (string)$message, 'context' => $context ]; + } + + public function warning(string|\Stringable $message, array $context = []): void { + $this->logs[] = [ 'level' => 'warning', 'message' => (string)$message, 'context' => $context ]; + } + + public function notice(string|\Stringable $message, array $context = []): void { + $this->logs[] = [ 'level' => 'notice', 'message' => (string)$message, 'context' => $context ]; + } + + public function info(string|\Stringable $message, array $context = []): void { + $this->logs[] = [ 'level' => 'info', 'message' => (string)$message, 'context' => $context ]; + } + + public function debug(string|\Stringable $message, array $context = []): void { + $this->logs[] = [ 'level' => 'debug', 'message' => (string)$message, 'context' => $context ]; + } + + public function log($level, string|\Stringable $message, array $context = []): void { + $this->logs[] = [ 'level' => $level, 'message' => (string)$message, 'context' => $context ]; + } + +} diff --git a/README.md b/README.md index fd56fcc..853a6db 100644 --- a/README.md +++ b/README.md @@ -4,64 +4,15 @@ [![buddy pipeline](https://app.buddy.works/cloudobjects/cloudobjects-php-sdk/pipelines/pipeline/561203/badge.svg?token=40c63ec4ea9e432a9edc8ebfb0ba0e203f70a02a8208339b119ff16772f4abd4 "buddy pipeline")](https://app.buddy.works/cloudobjects/cloudobjects-php-sdk/pipelines/pipeline/561203) -The CloudObjects PHP SDK provides simple access to [CloudObjects](https://cloudobjects.io/) from PHP-based applications. It wraps the [Object API](https://coid.link/cloudobjects.io/ObjectAPI/1.0) to fetch objects from the CloudObjects Core database and provides object-based access to their RDF description. A two-tiered caching mechanism (in-memory and Doctrine cache drivers) is included. The SDK also contains a helper class to validate COIDs. - ## Installation -The SDK is [distributed through packagist](https://packagist.org/packages/cloudobjects/sdk). Add `cloudobjects/sdk` to the `require` section of your `composer.json`, like this: +The SDK is [distributed through packagist](https://packagist.org/packages/cloudobjects/sdk). -````json -{ - "require": { - "cloudobjects/sdk" : ">=0.7" - } -} -```` +Install with the following command: -## Retrieving Objects - -In order to retrieve objects from the CloudObjects Core database you need to create an instance of `CloudObjects\SDK\ObjectRetriever`. Then you can call `getObject()`. This method returns an `ML\JsonLD\Node` instance or `null` if the object is not found. You can use the object interface of the [JsonLD library](https://github.com/lanthaler/JsonLD/) to read the information from the object. - -Here's a simple example: - -````php -use ML\IRI\IRI; -use CloudObjects\SDK\ObjectRetriever; - -/* ... */ - -$retriever = new ObjectRetriever(); -$object = $this->retriever->getObject(new IRI('coid://cloudobjects.io')); -if (isset($object)) - echo $object->getProperty('http://www.w3.org/2000/01/rdf-schema#label')->getValue(); -else - echo "Object not found."; -```` - -### Configuration - -You can pass an array of configuration options to the ObjectRetriever's constructor: - -| Option | Description | Default | -|---|---|---| -| `cache_provider` | The type of cache used. Currently supports `redis`, `file` and `none`. | `none` | -| `cache_prefix` | A prefix used for cache IDs. Normally this should not be set but might be necessary on shared caches. | `clobj:` | -| `cache_ttl` | Determines how long objects can remain cached. | `60` | -| `auth_ns` | The namespace of the service that this retriever acts for. If not set the API is accessed anonymously. | `null` | -| `auth_secret` | The shared secret between the namespace in `auth_ns` and `cloudobjects.io` for authenticated. If not set the API is accessed anonymously. | `null` | - -#### For `redis` cache: - -| Option | Description | Default | -|---|---|---| -| `cache_provider.redis.host` | The hostname or IP of the Redis instance. | `127.0.0.1` | -| `cache_provider.redis.port` | The port number of the Redis instance. | `6379` | - -#### For `file` cache: - -| Option | Description | Default | -|---|---|---| -| `cache_provider.file.directory` | The directory to store cache data in. | The system's temporary directory. | +``` +composer require cloudobjects/laravel-sdk +``` ## License diff --git a/composer.json b/composer.json index a60ea62..1840a96 100644 --- a/composer.json +++ b/composer.json @@ -6,12 +6,12 @@ "license": "MPL-2.0", "require" : { "ml/json-ld": ">=1.0.7", - "doctrine/common" : ">=2.6.1", - "doctrine/cache" : "1.*", "guzzlehttp/guzzle" : ">=6.0", + "psr/cache": ">=1.0", "psr/log": ">=1.1", "kevinrob/guzzle-cache-middleware": "^7.0.0", - "webmozart/assert": "^1.6" + "webmozart/assert": "^1.6", + "psr/simple-cache": "^3.0" }, "authors": [ { diff --git a/composer.lock b/composer.lock index f35e02d..e875139 100644 --- a/composer.lock +++ b/composer.lock @@ -4,395 +4,20 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "c3afb3b29d3f46223386d29810f6e8d5", + "content-hash": "659b8e6e4e495bf62452eb85772ac9aa", "packages": [ - { - "name": "doctrine/cache", - "version": "1.13.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/cache.git", - "reference": "56cd022adb5514472cb144c087393c1821911d09" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/cache/zipball/56cd022adb5514472cb144c087393c1821911d09", - "reference": "56cd022adb5514472cb144c087393c1821911d09", - "shasum": "" - }, - "require": { - "php": "~7.1 || ^8.0" - }, - "conflict": { - "doctrine/common": ">2.2,<2.4" - }, - "require-dev": { - "alcaeus/mongo-php-adapter": "^1.1", - "cache/integration-tests": "dev-master", - "doctrine/coding-standard": "^9", - "mongodb/mongodb": "^1.1", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "predis/predis": "~1.0", - "psr/cache": "^1.0 || ^2.0 || ^3.0", - "symfony/cache": "^4.4 || ^5.4 || ^6", - "symfony/var-exporter": "^4.4 || ^5.4 || ^6" - }, - "suggest": { - "alcaeus/mongo-php-adapter": "Required to use legacy MongoDB driver" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "PHP Doctrine Cache library is a popular cache implementation that supports many different drivers such as redis, memcache, apc, mongodb and others.", - "homepage": "https://www.doctrine-project.org/projects/cache.html", - "keywords": [ - "abstraction", - "apcu", - "cache", - "caching", - "couchdb", - "memcached", - "php", - "redis", - "xcache" - ], - "support": { - "issues": "https://github.com/doctrine/cache/issues", - "source": "https://github.com/doctrine/cache/tree/1.13.0" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fcache", - "type": "tidelift" - } - ], - "abandoned": true, - "time": "2022-05-20T20:06:54+00:00" - }, - { - "name": "doctrine/common", - "version": "3.5.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/common.git", - "reference": "d9ea4a54ca2586db781f0265d36bea731ac66ec5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/common/zipball/d9ea4a54ca2586db781f0265d36bea731ac66ec5", - "reference": "d9ea4a54ca2586db781f0265d36bea731ac66ec5", - "shasum": "" - }, - "require": { - "doctrine/persistence": "^2.0 || ^3.0 || ^4.0", - "php": "^7.1 || ^8.0" - }, - "require-dev": { - "doctrine/coding-standard": "^9.0 || ^10.0", - "doctrine/collections": "^1", - "phpstan/phpstan": "^1.4.1", - "phpstan/phpstan-phpunit": "^1", - "phpunit/phpunit": "^7.5.20 || ^8.5 || ^9.0", - "squizlabs/php_codesniffer": "^3.0", - "symfony/phpunit-bridge": "^6.1", - "vimeo/psalm": "^4.4" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Common\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - }, - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com" - } - ], - "description": "PHP Doctrine Common project is a library that provides additional functionality that other Doctrine projects depend on such as better reflection support, proxies and much more.", - "homepage": "https://www.doctrine-project.org/projects/common.html", - "keywords": [ - "common", - "doctrine", - "php" - ], - "support": { - "issues": "https://github.com/doctrine/common/issues", - "source": "https://github.com/doctrine/common/tree/3.5.0" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fcommon", - "type": "tidelift" - } - ], - "time": "2025-01-01T22:12:03+00:00" - }, - { - "name": "doctrine/event-manager", - "version": "2.1.1", - "source": { - "type": "git", - "url": "https://github.com/doctrine/event-manager.git", - "reference": "dda33921b198841ca8dbad2eaa5d4d34769d18cf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/event-manager/zipball/dda33921b198841ca8dbad2eaa5d4d34769d18cf", - "reference": "dda33921b198841ca8dbad2eaa5d4d34769d18cf", - "shasum": "" - }, - "require": { - "php": "^8.1" - }, - "conflict": { - "doctrine/common": "<2.9" - }, - "require-dev": { - "doctrine/coding-standard": "^14", - "phpdocumentor/guides-cli": "^1.4", - "phpstan/phpstan": "^2.1.32", - "phpunit/phpunit": "^10.5.58" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Common\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - }, - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com" - } - ], - "description": "The Doctrine Event Manager is a simple PHP event system that was built to be used with the various Doctrine projects.", - "homepage": "https://www.doctrine-project.org/projects/event-manager.html", - "keywords": [ - "event", - "event dispatcher", - "event manager", - "event system", - "events" - ], - "support": { - "issues": "https://github.com/doctrine/event-manager/issues", - "source": "https://github.com/doctrine/event-manager/tree/2.1.1" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fevent-manager", - "type": "tidelift" - } - ], - "time": "2026-01-29T07:11:08+00:00" - }, - { - "name": "doctrine/persistence", - "version": "4.1.1", - "source": { - "type": "git", - "url": "https://github.com/doctrine/persistence.git", - "reference": "b9c49ad3558bb77ef973f4e173f2e9c2eca9be09" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/persistence/zipball/b9c49ad3558bb77ef973f4e173f2e9c2eca9be09", - "reference": "b9c49ad3558bb77ef973f4e173f2e9c2eca9be09", - "shasum": "" - }, - "require": { - "doctrine/event-manager": "^1 || ^2", - "php": "^8.1", - "psr/cache": "^1.0 || ^2.0 || ^3.0" - }, - "require-dev": { - "doctrine/coding-standard": "^14", - "phpstan/phpstan": "2.1.30", - "phpstan/phpstan-phpunit": "^2", - "phpstan/phpstan-strict-rules": "^2", - "phpunit/phpunit": "^10.5.58 || ^12", - "symfony/cache": "^4.4 || ^5.4 || ^6.0 || ^7.0", - "symfony/finder": "^4.4 || ^5.4 || ^6.0 || ^7.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Persistence\\": "src/Persistence" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - }, - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com" - } - ], - "description": "The Doctrine Persistence project is a set of shared interfaces and functionality that the different Doctrine object mappers share.", - "homepage": "https://www.doctrine-project.org/projects/persistence.html", - "keywords": [ - "mapper", - "object", - "odm", - "orm", - "persistence" - ], - "support": { - "issues": "https://github.com/doctrine/persistence/issues", - "source": "https://github.com/doctrine/persistence/tree/4.1.1" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fpersistence", - "type": "tidelift" - } - ], - "time": "2025-10-16T20:13:18+00:00" - }, { "name": "guzzlehttp/guzzle", - "version": "7.10.0", + "version": "7.10.4", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "b51ac707cfa420b7bfd4e4d5e510ba8008e822b4" + "reference": "aec528da477062d3af11f51e6b33402be233b21f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/b51ac707cfa420b7bfd4e4d5e510ba8008e822b4", - "reference": "b51ac707cfa420b7bfd4e4d5e510ba8008e822b4", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/aec528da477062d3af11f51e6b33402be233b21f", + "reference": "aec528da477062d3af11f51e6b33402be233b21f", "shasum": "" }, "require": { @@ -410,8 +35,9 @@ "bamarni/composer-bin-plugin": "^1.8.2", "ext-curl": "*", "guzzle/client-integration-tests": "3.0.2", + "guzzlehttp/test-server": "^0.3.2", "php-http/message-factory": "^1.1", - "phpunit/phpunit": "^8.5.39 || ^9.6.20", + "phpunit/phpunit": "^8.5.52 || ^9.6.34", "psr/log": "^1.1 || ^2.0 || ^3.0" }, "suggest": { @@ -489,7 +115,7 @@ ], "support": { "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/7.10.0" + "source": "https://github.com/guzzle/guzzle/tree/7.10.4" }, "funding": [ { @@ -505,20 +131,20 @@ "type": "tidelift" } ], - "time": "2025-08-23T22:36:01+00:00" + "time": "2026-05-22T19:00:53+00:00" }, { "name": "guzzlehttp/promises", - "version": "2.3.0", + "version": "2.4.1", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "481557b130ef3790cf82b713667b43030dc9c957" + "reference": "09e8a212562fb1fb6a512c4156ed71525969d6c2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/481557b130ef3790cf82b713667b43030dc9c957", - "reference": "481557b130ef3790cf82b713667b43030dc9c957", + "url": "https://api.github.com/repos/guzzle/promises/zipball/09e8a212562fb1fb6a512c4156ed71525969d6c2", + "reference": "09e8a212562fb1fb6a512c4156ed71525969d6c2", "shasum": "" }, "require": { @@ -526,7 +152,7 @@ }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", - "phpunit/phpunit": "^8.5.44 || ^9.6.25" + "phpunit/phpunit": "^8.5.52 || ^9.6.34" }, "type": "library", "extra": { @@ -572,7 +198,7 @@ ], "support": { "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/2.3.0" + "source": "https://github.com/guzzle/promises/tree/2.4.1" }, "funding": [ { @@ -588,20 +214,20 @@ "type": "tidelift" } ], - "time": "2025-08-22T14:34:08+00:00" + "time": "2026-05-20T22:57:30+00:00" }, { "name": "guzzlehttp/psr7", - "version": "2.8.0", + "version": "2.10.2", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "21dc724a0583619cd1652f673303492272778051" + "reference": "a1bbdc172f32a25fe999965b65b6e71fd87da9ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/21dc724a0583619cd1652f673303492272778051", - "reference": "21dc724a0583619cd1652f673303492272778051", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/a1bbdc172f32a25fe999965b65b6e71fd87da9ed", + "reference": "a1bbdc172f32a25fe999965b65b6e71fd87da9ed", "shasum": "" }, "require": { @@ -616,8 +242,9 @@ }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8.2", - "http-interop/http-factory-tests": "0.9.0", - "phpunit/phpunit": "^8.5.44 || ^9.6.25" + "http-interop/http-factory-tests": "1.1.0", + "jshttp/mime-db": "1.54.0.1", + "phpunit/phpunit": "^8.5.52 || ^9.6.34" }, "suggest": { "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" @@ -688,7 +315,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.8.0" + "source": "https://github.com/guzzle/psr7/tree/2.10.2" }, "funding": [ { @@ -704,7 +331,7 @@ "type": "tidelift" } ], - "time": "2025-08-23T21:21:41+00:00" + "time": "2026-05-25T22:58:15+00:00" }, { "name": "kevinrob/guzzle-cache-middleware", @@ -1151,6 +778,57 @@ }, "time": "2024-09-11T13:17:53+00:00" }, + { + "name": "psr/simple-cache", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/simple-cache.git", + "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/764e0b3939f5ca87cb904f570ef9be2d78a07865", + "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\SimpleCache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interfaces for simple caching", + "keywords": [ + "cache", + "caching", + "psr", + "psr-16", + "simple-cache" + ], + "support": { + "source": "https://github.com/php-fig/simple-cache/tree/3.0.0" + }, + "time": "2021-10-29T13:26:27+00:00" + }, { "name": "ralouphie/getallheaders", "version": "3.0.3", @@ -1197,16 +875,16 @@ }, { "name": "symfony/deprecation-contracts", - "version": "v3.6.0", + "version": "v3.7.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62" + "reference": "50f59d1f3ca46d41ac911f97a78626b6756af35b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62", - "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/50f59d1f3ca46d41ac911f97a78626b6756af35b", + "reference": "50f59d1f3ca46d41ac911f97a78626b6756af35b", "shasum": "" }, "require": { @@ -1219,7 +897,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.6-dev" + "dev-main": "3.7-dev" } }, "autoload": { @@ -1244,7 +922,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.7.0" }, "funding": [ { @@ -1255,12 +933,16 @@ "url": "https://github.com/fabpot", "type": "github" }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, { "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", "type": "tidelift" } ], - "time": "2024-09-25T14:21:43+00:00" + "time": "2026-04-13T15:52:40+00:00" }, { "name": "webmozart/assert", @@ -2348,6 +2030,7 @@ "type": "github" } ], + "abandoned": true, "time": "2023-02-03T06:58:43+00:00" }, { @@ -2403,6 +2086,7 @@ "type": "github" } ], + "abandoned": true, "time": "2023-02-03T06:59:15+00:00" }, { @@ -3192,16 +2876,16 @@ }, { "name": "symfony/http-foundation", - "version": "v7.4.5", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "446d0db2b1f21575f1284b74533e425096abdfb6" + "reference": "9381209597ec66c25be154cbf2289076e64d1eab" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/446d0db2b1f21575f1284b74533e425096abdfb6", - "reference": "446d0db2b1f21575f1284b74533e425096abdfb6", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/9381209597ec66c25be154cbf2289076e64d1eab", + "reference": "9381209597ec66c25be154cbf2289076e64d1eab", "shasum": "" }, "require": { @@ -3250,7 +2934,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v7.4.5" + "source": "https://github.com/symfony/http-foundation/tree/v7.4.8" }, "funding": [ { @@ -3270,20 +2954,20 @@ "type": "tidelift" } ], - "time": "2026-01-27T16:16:02+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.33.0", + "version": "v1.38.1", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493" + "reference": "14c5439eec4ccff081ac14eca2dc57feb2a66d92" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493", - "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/14c5439eec4ccff081ac14eca2dc57feb2a66d92", + "reference": "14c5439eec4ccff081ac14eca2dc57feb2a66d92", "shasum": "" }, "require": { @@ -3335,7 +3019,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.33.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.38.1" }, "funding": [ { @@ -3355,20 +3039,20 @@ "type": "tidelift" } ], - "time": "2024-12-23T08:48:59+00:00" + "time": "2026-05-26T12:51:13+00:00" }, { "name": "symfony/psr-http-message-bridge", - "version": "v7.4.4", + "version": "v7.4.8", "source": { "type": "git", "url": "https://github.com/symfony/psr-http-message-bridge.git", - "reference": "929ffe10bbfbb92e711ac3818d416f9daffee067" + "reference": "76f1a57719a4a04c0ea18678a6c9305b5dcb9da8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/929ffe10bbfbb92e711ac3818d416f9daffee067", - "reference": "929ffe10bbfbb92e711ac3818d416f9daffee067", + "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/76f1a57719a4a04c0ea18678a6c9305b5dcb9da8", + "reference": "76f1a57719a4a04c0ea18678a6c9305b5dcb9da8", "shasum": "" }, "require": { @@ -3423,7 +3107,7 @@ "psr-7" ], "support": { - "source": "https://github.com/symfony/psr-http-message-bridge/tree/v7.4.4" + "source": "https://github.com/symfony/psr-http-message-bridge/tree/v7.4.8" }, "funding": [ { @@ -3443,7 +3127,7 @@ "type": "tidelift" } ], - "time": "2026-01-03T23:30:35+00:00" + "time": "2026-03-24T13:12:05+00:00" }, { "name": "theseer/tokenizer", diff --git a/tests/OnlineTests/ObjectRetrieverCacheTest.php b/tests/OnlineTests/ObjectRetrieverCacheTest.php new file mode 100644 index 0000000..9b3d78c --- /dev/null +++ b/tests/OnlineTests/ObjectRetrieverCacheTest.php @@ -0,0 +1,47 @@ + $cacheStorage, + 'logger' => $logger + ]); + + $object1 = $retriever->getCloudObject($coid); + + $this->assertNotNull($object1); + $this->assertNotNull($cacheStorage->fetch($retriever->getCacheKey((string)$coid))); + $this->assertStringContainsString('from Core API', $logger->getLastLogMessage()); + + // Reinitialize retriever with same cache storage to verify that cache is used + $retriever = new ObjectRetriever([ + 'cache_storage' => $cacheStorage, + 'logger' => $logger + ]); + + $object2 = $retriever->getCloudObject($coid); + + $this->assertNotNull($object2); + $this->assertNotNull($cacheStorage->fetch($retriever->getCacheKey((string)$coid))); + $this->assertStringContainsString('from object cache', $logger->getLastLogMessage()); + + $this->assertEquals($object1->getRevision(), $object2->getRevision()); + } + +}