Skip to content

Commit 9e5f006

Browse files
committed
refactor: provide Capabilities as a read-only class
This also removes `capability` event and the `marker` object. Capabilities are meant to be read-only and thus won't change after retrieval via `StorageInterface#getCapabilties`. By having the event deleted, there is no need to have the adapter injected, though we also removed `Capabilities#getAdapter` and the `StorageInterface` constructor argument. By refactoring the `Serializer` plugin, which already replaced the initial instance of `Capabilities`, we were able to drop the `base capabilities` feature as well. Final result is that we now provide all capabilities as public `read-only` properties which reflect their defaults which were previously handled via internal `$default` magic in `Capabilties#getCapability`. Along all the refactoring, some capabilities have changed or were removed while respecting ideas of #8 which was around since 2016: - `staticTtl` got removed without a replacement. It outlined if the cache backend is handling cache expiry or if the implementation is taking care of it. Though it might be interesting for picking a specific backend, that is rather not of interest at runtime for upstream projects. - `lockOnExpire` got removed without a replacement. Was only used in zend-server adapter which is already abandoned since 2022 - `minTtl` got renamed to `ttlSupported` and its type changed from `int` to `bool` - `maxTtl` got removed without a replacement. Every cache backend which is supported by laminas right now does allow TTLs being an infinite amount of seconds (where maximum `int` range is the limit, depending on the CPU architecture). There was a backend `XCache` where a limit existed but that backend was abandoned in 2021. - `useRequestTime` was renamed to `usesRequestTime` - `namespaceSeparator` got removed without a replacement. It was reflecting the option value and this the storage options can be used instead. Signed-off-by: Maximilian Bösing <[email protected]>
1 parent 83587e7 commit 9e5f006

15 files changed

+198
-969
lines changed

docs/book/v4/storage/adapter.md

+32-63
Original file line numberDiff line numberDiff line change
@@ -515,15 +515,11 @@ This adapter implements the following interfaces:
515515
| Capability | Value |
516516
|----------------------|---------------------------------------------------------------------------------------|
517517
| `supportedDatatypes` | `null`, `bool`, `int`, `float`, `string`, `array` (serialized), `object` (serialized) |
518-
| `minTtl` | 1 |
519-
| `maxTtl` | 0 |
520-
| `staticTtl` | `true` |
521-
| `ttlPrecision` | 1 |
522-
| `useRequestTime` | value of `apc.use_request_time` from `php.ini` |
523-
| `lockOnExpire` | 0 |
524-
| `maxKeyLength` | 5182 |
518+
| `ttlSupported` | `true` |
519+
| `ttlPrecision` | `1` |
520+
| `usesRequestTime` | value of `apc.use_request_time` INI value, disabled by default. |
521+
| `maxKeyLength` | `5182` |
525522
| `namespaceIsPrefix` | `true` |
526-
| `namespaceSeparator` | Option value of `namespace_separator` |
527523

528524
### Metadata
529525

@@ -570,15 +566,11 @@ This adapter implements the following interfaces:
570566
| Capability | Value |
571567
|----------------------|-------------------------------------------------------------|
572568
| `supportedDatatypes` | `null`, `bool`, `int`, `float`, `string`, `array`, `object` |
573-
| `minTtl` | 1 |
574-
| `maxTtl` | 0 |
575-
| `staticTtl` | `false` or `true`, depending on `psr` option |
576-
| `ttlPrecision` | 1 |
577-
| `useRequestTime` | false |
578-
| `lockOnExpire` | 0 |
579-
| `maxKeyLength` | -1 |
569+
| `ttlSupported` | `true` |
570+
| `ttlPrecision` | `1` |
571+
| `usesRequestTime` | `false` |
572+
| `maxKeyLength` | unlimited as nothing will be cached anyways |
580573
| `namespaceIsPrefix` | `true` |
581-
| `namespaceSeparator` | none |
582574

583575
## Filesystem Adapter
584576

@@ -602,15 +594,11 @@ This adapter implements the following interfaces:
602594
| Capability | Value |
603595
|----------------------|--------------------------------------------------------------------------------------------------|
604596
| `supportedDatatypes` | `string`, `null` => `string`, `boolean` => `string`, `integer` => `string`, `double` => `string` |
605-
| `minTtl` | 1 |
606-
| `maxTtl` | 0 |
607-
| `staticTtl` | `false` |
608-
| `ttlPrecision` | 1 |
609-
| `useRequestTime` | `false` |
610-
| `lockOnExpire` | 0 |
611-
| `maxKeyLength` | 251 |
597+
| `ttlSupported` | `true` |
598+
| `ttlPrecision` | `1` |
599+
| `usesRequestTime` | `false` |
600+
| `maxKeyLength` | `251` |
612601
| `namespaceIsPrefix` | `true` |
613-
| `namespaceSeparator` | Option value of `namespace_separator` |
614602

615603
### Metadata
616604

@@ -661,15 +649,11 @@ This adapter implements the following interfaces:
661649
| Capability | Value |
662650
|----------------------|-----------------------------------------------------------------------------------------------|
663651
| `supportedDatatypes` | `null`, `boolean`, `integer`, `double`, `string`, `array` (serialized), `object` (serialized) |
664-
| `minTtl` | 1 |
665-
| `maxTtl` | 0 |
666-
| `staticTtl` | `true` |
667-
| `ttlPrecision` | 1 |
668-
| `useRequestTime` | `false` |
669-
| `lockOnExpire` | 0 |
670-
| `maxKeyLength` | 255 |
652+
| `ttlSupported` | `true` |
653+
| `ttlPrecision` | `1` |
654+
| `usesRequestTime` | `false` |
655+
| `maxKeyLength` | `255` |
671656
| `namespaceIsPrefix` | `true` |
672-
| `namespaceSeparator` | none |
673657

674658
### Adapter Specific Options
675659

@@ -695,15 +679,11 @@ This adapter implements the following interfaces:
695679
| Capability | Value |
696680
|----------------------|-------------------------------------------------------|
697681
| `supportedDatatypes` | `string`, `array` (serialized), `object` (serialized) |
698-
| `minTtl` | 1 |
699-
| `maxTtl` | 0 |
700-
| `staticTtl` | `true` |
701-
| `ttlPrecision` | 1 |
702-
| `useRequestTime` | `false` |
703-
| `lockOnExpire` | 0 |
704-
| `maxKeyLength` | 512000000 (in Redis v3+, 255 otherwise) |
682+
| `ttlSupported` | `true` |
683+
| `ttlPrecision` | `1` |
684+
| `usesRequestTime` | `false` |
685+
| `maxKeyLength` | `512000000` (in Redis v3+, `255` in older versions) |
705686
| `namespaceIsPrefix` | `true` |
706-
| `namespaceSeparator` | none |
707687

708688
### Metadata
709689

@@ -745,15 +725,11 @@ This adapter implements the following interfaces:
745725
| Capability | Value |
746726
|----------------------|-------------------------------------------------------|
747727
| `supportedDatatypes` | `string`, `array` (serialized), `object` (serialized) |
748-
| `minTtl` | 1 |
749-
| `maxTtl` | 0 |
750-
| `staticTtl` | `true` |
751-
| `ttlPrecision` | 1 |
752-
| `useRequestTime` | `false` |
753-
| `lockOnExpire` | 0 |
754-
| `maxKeyLength` | 512000000 (in Redis v3+, 255 otherwise) |
728+
| `ttlSupported` | `true` |
729+
| `ttlPrecision` | `1` |
730+
| `usesRequestTime` | `false` |
731+
| `maxKeyLength` | `512000000` (in Redis v3+, `255` in older versions) |
755732
| `namespaceIsPrefix` | `true` |
756-
| `namespaceSeparator` | none |
757733

758734
### Metadata
759735

@@ -796,13 +772,10 @@ This adapter implements the following interfaces:
796772
| Capability | Value |
797773
|----------------------|---------------------------------------------------------------------------------|
798774
| `supportedDatatypes` | `string`, `null`, `boolean`, `integer`, `double`, `array`, `object`, `resource` |
799-
| `minTtl` | 1 |
800-
| `maxTtl` | Value of `PHP_INT_MAX` |
801-
| `staticTtl` | `false` |
802-
| `ttlPrecision` | 0.05 |
803-
| `useRequestTime` | `false` |
804-
| `lockOnExpire` | 0 |
805-
| `maxKeyLength` | 0 |
775+
| `ttlSupported` | `true` |
776+
| `ttlPrecision` | `0.05` |
777+
| `usesRequestTime` | `false` |
778+
| `maxKeyLength` | `0` |
806779
| `namespaceIsPrefix` | `false` |
807780

808781
### Metadata
@@ -851,15 +824,11 @@ This adapter implements the following interfaces:
851824
| Capability | Value |
852825
|----------------------|-----------------------------------------------------------|
853826
| `supportedDatatypes` | `string`, `null`, `boolean`, `integer`, `double`, `array` |
854-
| `minTtl` | 0 |
855-
| `maxTtl` | 0 |
856-
| `staticTtl` | `true` |
857-
| `ttlPrecision` | 1 |
858-
| `useRequestTime` | `false` |
859-
| `lockOnExpire` | 0 |
860-
| `maxKeyLength` | 255 |
827+
| `ttlSupported` | `true` |
828+
| `ttlPrecision` | `1` |
829+
| `usesRequestTime` | `false` |
830+
| `maxKeyLength` | `255` |
861831
| `namespaceIsPrefix` | `true` |
862-
| `namespaceSeparator` | *Option value of `namespace_separator`* |
863832

864833
### Metadata
865834

docs/book/v4/storage/capabilities.md

+24-173
Original file line numberDiff line numberDiff line change
@@ -24,156 +24,32 @@ use stdClass;
2424
use Laminas\Cache\Exception;
2525
use Laminas\EventManager\EventsCapableInterface;
2626

27-
class Capabilities
27+
final class Capabilities
2828
{
2929
/**
30-
* Constructor
31-
*
30+
* @param int<-1,max> $maxKeyLength
31+
* @param SupportedDataTypesArrayShape $supportedDataTypes
3232
*/
3333
public function __construct(
34-
StorageInterface $storage,
35-
stdClass $marker,
36-
array $capabilities = [],
37-
Capabilities|null $baseCapabilities = null
38-
);
39-
40-
/**
41-
* Get the storage adapter
42-
*/
43-
public function getAdapter(): StorageInterface;
44-
45-
/**
46-
* Get supported datatypes
47-
*/
48-
public function getSupportedDatatypes(): array;
49-
50-
/**
51-
* Set supported datatypes
52-
*
53-
* @param stdClass $marker
54-
* @param array $datatypes
55-
* @throws Exception\InvalidArgumentException
56-
* @return Capabilities Fluent interface
57-
*/
58-
public function setSupportedDatatypes(stdClass $marker, array $datatypes);
59-
60-
/**
61-
* Get minimum supported time-to-live
62-
*
63-
* @return int 0 means items never expire
64-
*/
65-
public function getMinTtl(): int;
66-
67-
/**
68-
* Set minimum supported time-to-live
69-
*
70-
* @param stdClass $marker
71-
* @param int $minTtl
72-
* @throws Exception\InvalidArgumentException
73-
*/
74-
public function setMinTtl(stdClass $marker, int $minTtl): self;
75-
76-
/**
77-
* Get maximum supported time-to-live
78-
*
79-
* @return int 0 means infinite
80-
*/
81-
public function getMaxTtl(): int;
82-
83-
/**
84-
* Set maximum supported time-to-live
85-
*
86-
* @throws Exception\InvalidArgumentException
87-
*/
88-
public function setMaxTtl(stdClass $marker, int $maxTtl): self;
89-
90-
/**
91-
* Is the time-to-live handled static (on write)
92-
* or dynamic (on read)
93-
*/
94-
public function getStaticTtl(): bool;
95-
96-
/**
97-
* Set if the time-to-live handled static (on write) or dynamic (on read)
98-
*/
99-
public function setStaticTtl(stdClass $marker, bool $flag): self;
100-
101-
/**
102-
* Get time-to-live precision
103-
*/
104-
public function getTtlPrecision(): float;
105-
106-
/**
107-
* Set time-to-live precision
108-
*
109-
* @throws Exception\InvalidArgumentException
110-
*/
111-
public function setTtlPrecision(stdClass $marker, float $ttlPrecision): self;
112-
113-
/**
114-
* Get use request time
115-
*/
116-
public function getUseRequestTime(): bool;
117-
118-
/**
119-
* Set use request time
120-
*/
121-
public function setUseRequestTime(stdClass $marker, bool $flag): self;
122-
123-
124-
/**
125-
* Get "lock-on-expire" support in seconds.
126-
*
127-
* @return int 0 = Expired items will never be retrieved
128-
* >0 = Time in seconds an expired item could be retrieved
129-
* -1 = Expired items could be retrieved forever
130-
*/
131-
public function getLockOnExpire(): int
132-
{
133-
return $this->getCapability('lockOnExpire', 0);
134-
}
135-
136-
/**
137-
* Set "lock-on-expire" support in seconds.
138-
*/
139-
public function setLockOnExpire(stdClass $marker, int $timeout): self
140-
{
141-
return $this->setCapability($marker, 'lockOnExpire', (int) $timeout);
34+
/**
35+
* Maximum supported key length for the cache backend
36+
*/
37+
public readonly int $maxKeyLength,
38+
/**
39+
* Whether the cache backend supports TTL
40+
*/
41+
public readonly bool $ttlSupported,
42+
public readonly bool $namespaceIsPrefix,
43+
/**
44+
* Contains the supported data types.
45+
* Depending on the cache backend in use, the type remains as is, is converted to a different type or is not
46+
* supported at all.
47+
*/
48+
public readonly array $supportedDataTypes,
49+
public readonly int|float $ttlPrecision,
50+
public readonly bool $usesRequestTime,
51+
) {
14252
}
143-
144-
/**
145-
* Get maximum key length
146-
*
147-
* @return int -1 means unknown, 0 means infinite
148-
*/
149-
public function getMaxKeyLength(): int;
150-
151-
/**
152-
* Set maximum key length
153-
*
154-
* @throws Exception\InvalidArgumentException
155-
*/
156-
public function setMaxKeyLength(stdClass $marker, int $maxKeyLength): self;
157-
158-
/**
159-
* Get if namespace support is implemented as prefix
160-
*/
161-
public function getNamespaceIsPrefix(): bool;
162-
163-
/**
164-
* Set if namespace support is implemented as prefix
165-
*/
166-
public function setNamespaceIsPrefix(stdClass $marker, bool $flag): self;
167-
168-
/**
169-
* Get namespace separator if namespace is implemented as prefix
170-
*/
171-
public function getNamespaceSeparator(): string;
172-
173-
/**
174-
* Set the namespace separator if namespace is implemented as prefix
175-
*/
176-
public function setNamespaceSeparator(stdClass $marker, string $separator): self;
17753
}
17854
```
17955

@@ -192,37 +68,12 @@ $container = null; // can be any configured PSR-11 container
19268
$storageFactory = $container->get(StorageAdapterFactoryInterface::class);
19369

19470
$cache = $storageFactory->create('filesystem');
195-
$supportedDatatypes = $cache->getCapabilities()->getSupportedDatatypes();
71+
$supportedDataTypes = $cache->getCapabilities()->supportedDataTypes;
19672

19773
// now you can run specific stuff in base of supported feature
198-
if ($supportedDatatypes['object']) {
74+
if ($supportedDataTypes['object']) {
19975
$cache->set($key, $object);
20076
} else {
20177
$cache->set($key, serialize($object));
20278
}
203-
```
204-
205-
### Listen to the change Event
206-
207-
```php
208-
use Laminas\Cache\Service\StorageAdapterFactoryInterface;
209-
use Psr\Container\ContainerInterface;
210-
211-
/** @var ContainerInterface $container */
212-
$container = null; // can be any configured PSR-11 container
213-
214-
/** @var StorageAdapterFactoryInterface $storageFactory */
215-
$storageFactory = $container->get(StorageAdapterFactoryInterface::class);
216-
217-
$cache = $storageFactory->create('filesystem', [
218-
'no_atime' => false,
219-
]);
220-
221-
// Catching capability changes
222-
$cache->getEventManager()->attach('capability', function($event) {
223-
echo count($event->getParams()) . ' capabilities changed';
224-
});
225-
226-
// change option which changes capabilities
227-
$cache->getOptions()->setNoATime(true);
228-
```
79+
```

0 commit comments

Comments
 (0)