\Drupal\strata\Storage\Plugin\Strata\Storage LocalStorage

Stores objects on the local filesystem.

Three real uses: the kernel test lane, which needs a store with no network; a staging tier a site can flush to before a slower upload; and a target for an export a human is going to copy.

Writes are atomic. Every object lands in a temporary file in the same directory and is renamed into place, so a crash mid-write leaves either the previous object or none, never a half one. A reader that saw a truncated object would treat it as a corrupt frame and quarantine a commit that is actually intact.

Summary

Methods
Properties
Constants
__construct
root
id
label
capabilities
isReachable
unreachableReason
get
stream
head
exists
put
delete
list
No public properties found
No public constants found
No protected methods found
No protected properties found
No protected constants found
missingWrapper
resolve
isReserved
normalize
makeDirectory
pruneEmptyDirectories
walk
copyStream
etag
root
DIRECTORY_MODE
COPY_CHUNK
RESERVED_SUFFIX

Constant

DIRECTORY_MODE

DIRECTORY_MODE = 0755

Directory mode for created directories.

COPY_CHUNK

COPY_CHUNK = 1048576

Bytes copied per iteration when streaming a body in.

RESERVED_SUFFIX

RESERVED_SUFFIX = '.tmp'

Suffix the atomic-write mechanism reserves for a write in progress.

A file carrying it is a partial write, so it is not an object: it is hidden from listings, reports absent from head and exists, and cannot be written to directly.

Properties

$root

$root : string

Absolute path to the store root, with no trailing slash.

Type

string

Methods

__construct()

__construct(string  $root) : mixed

Constructs a store.

Parameters

string $root

Directory the store lives in. Created on first write if absent.

Throws

\InvalidArgumentException

When the path is empty.

Returns

mixed —

root()

root() : string

The store root.

Returns

string —

Absolute path with no trailing slash.

id()

id() : string

The plugin id this provider registers under.

Returns

string —

A short lowercase token such as "s3", "r2", "sftp" or "local".

label()

label() : string

Human-readable name for the settings form.

Returns

string —

The label.

capabilities()

capabilities() : \Drupal\strata\Storage\Capabilities

What this endpoint can do.

Returns

\Drupal\strata\Storage\Capabilities —

The capability set.

isReachable()

isReachable() : bool

Whether the endpoint is reachable and the credentials work.

Returns

bool —

TRUE when a request would succeed right now.

unreachableReason()

unreachableReason() : string|null

Why the endpoint is unreachable.

Returns

string|null —

A short human-readable reason, or NULL when it is reachable.

get()

get(string  $key, ?\Drupal\strata\Storage\ByteRange  $range = null) : string

Reads an object.

Parameters

string $key

Object key relative to the store root.

?\Drupal\strata\Storage\ByteRange $range

A byte range, or NULL for the whole object.

Returns

string —

The bytes.

stream()

stream(string  $key) : resource

Opens an object as a stream.

Parameters

string $key

Object key relative to the store root.

Returns

resource —

An open readable stream the caller must close.

head()

head(string  $key) : \Drupal\strata\Storage\ObjectMeta|null

Metadata for one object without reading it.

Parameters

string $key

Object key relative to the store root.

Returns

\Drupal\strata\Storage\ObjectMeta|null —

The metadata, or NULL when the object is absent. Absence is not an error, because every caller of this method is asking precisely in order to find out.

exists()

exists(string  $key) : bool

Whether an object exists.

Parameters

string $key

Object key relative to the store root.

Returns

bool —

TRUE when it is present.

put()

put(string  $key, mixed  $body, array  $options = []) : \Drupal\strata\Storage\PutResult

Writes an object.

Parameters

string $key

Object key relative to the store root.

mixed $body

The bytes, or an open readable stream. A stream is read once and not rewound, so a caller that needs it again must seek itself.

array $options

Provider options. ifNoneMatch (write only when the key is absent) is honoured wherever Capabilities::$conditionalWrite is true. metadata, contentType and storageClass are honoured only by providers whose endpoint carries them; a provider that cannot store an option refuses the write rather than dropping it, because an object written without the metadata its reader expects is indistinguishable from a corrupt one. Nothing in the engine depends on user metadata: a stored object carries whatever a reader needs in its own bytes.

Returns

\Drupal\strata\Storage\PutResult —

What was written.

delete()

delete(array  $keys) : int

Deletes objects.

Parameters

array $keys

Object keys relative to the store root.

Returns

int —

How many keys the endpoint accepted. A store that can tell an absent key from a removed one counts only what it removed; S3 reports success for an absent key and cannot distinguish, so it counts everything it was given. Do not read this as "how many existed" - a prune receipt counts from the frame index, which knows.

list()

list(string  $prefix = '', ?string  $cursor = null, int  $limit = 1000, ?string  $delimiter = null) : \Drupal\strata\Storage\ObjectPage

Lists one page of objects under a prefix.

Parameters

string $prefix

Key prefix relative to the store root; an empty string lists everything.

?string $cursor

Continuation token from a previous page, or NULL to start.

int $limit

Most objects to return in this page.

?string $delimiter

Grouping delimiter, or NULL for a flat listing.

Returns

\Drupal\strata\Storage\ObjectPage —

The page.

missingWrapper()

missingWrapper() : string|null

Why the root's stream wrapper cannot be used, if it cannot.

A root may be a plain path or a stream URI, and private:// is the one a Drupal site is most likely to be pointed at. That scheme only exists once file_private_path is set, and every filesystem call against an unregistered scheme emits a PHP warning and answers FALSE - which reads as "the directory is missing" and sends an operator looking for the wrong thing.

Returns

string|null —

The reason, or NULL when the root is usable as far as its scheme goes.

resolve()

resolve(string  $key) : string

Turns a key into an absolute path, refusing anything that escapes the root.

A key arrives from a manifest, and a manifest can be tampered with, so a . or .. segment is rejected by name rather than normalised away: normalising one would silently address a different object than the manifest named.

A leading or trailing slash is the one thing that IS normalised, because it names the same object either way and an endpoint that keeps it produces a key with an empty first segment. /frames/aa therefore resolves inside the root rather than at the filesystem root.

Parameters

string $key

Object key relative to the store root.

Throws

\InvalidArgumentException

When the key is empty, has an empty inner segment, contains a . or .. segment or a null byte, or ends in the reserved in-progress suffix.

Returns

string —

Absolute path inside the root.

isReserved()

isReserved(string  $key) : bool

Whether a key names a write in progress rather than an object.

Parameters

string $key

The key or a single path segment.

Returns

bool —

TRUE when it carries the reserved suffix.

normalize()

normalize(string  $key) : string

Strips leading and trailing slashes from a key.

Parameters

string $key

The key.

Returns

string —

The key with no leading or trailing slash.

makeDirectory()

makeDirectory(string  $path) : void

Creates a directory and its parents.

Parameters

string $path

The directory.

Throws

\RuntimeException

When it cannot be created.

Returns

void —

pruneEmptyDirectories()

pruneEmptyDirectories(string  $path) : void

Removes directories left empty by a delete, up to the root.

A sharded store creates 65,536 directories; without this a bucket that has been fully pruned still carries all of them.

Parameters

string $path

The directory to start from.

Returns

void —

walk()

walk(string  $directory, string  $prefix) : list<string>

Collects every object key under a directory.

Parameters

string $directory

Absolute path to walk.

string $prefix

Key prefix accumulated so far.

Returns

list

Object keys relative to the store root.

copyStream()

copyStream(resource  $source, string  $destination, string  $key) : int

Copies a stream into a file.

Parameters

resource $source

An open readable stream.

string $destination

Path to write.

string $key

The object key, for error messages.

Throws

\RuntimeException

When either side fails.

Returns

int —

Bytes written.

etag()

etag(string  $path, int  $size) : string

An entity tag for a stored object.

Derived from size and modification time rather than content, so heading an object stays a stat rather than a read. Consumers treat an etag as opaque and compare it only to another etag from the same store.

Parameters

string $path

Absolute path to the object.

int $size

Size in bytes.

Returns

string —

The tag.