Skip to content

omnisense/omnimap API reference

Floor
Family
Version
1.x
Conformance suite
runs, CI green
Verified for real
Verified in part
Licence
MIT
composer require omnisense/omnimap:1.x-dev

Read from the package's own PHP files at the commit fd38b58a7f7e: its namespaces, classes, interfaces and enums, their public constants, properties and methods with their PHPDoc, and the options its factories take. Nothing of it is run.

Omnimap

  • Capabilities class

    What a provider is, said before it is asked anything: what it can do, and who it makes the visitor's browser or the server talk to.

    3 methods · 7 properties

  • Config class

    A provider's configuration while its factory builds it: the options given, the factory's defaults under them, and the keys that must be filled.

    7 methods

  • GeocoderInterface interface

    Places from an address, addresses from a point. omnimap does not geocode itself: Geocoding\GeocoderPhp asks a geocoder-php provider (willdurand/geocoder), with a cache and the pace the provider's terms set.

    2 methods

  • MapHtml class

    The map's element, as any host prints it (Twig, Blade, a React server render, plain PHP): either the picture kept in the cache, cut in tiles that assets/snapshot.js lays out, or a live map that assets/omnimap.js draws from the renderer's description.

    4 methods

  • MapPrinter class

    What a page shows of a view, whatever the host: the picture kept in the cache when there is one (made now by the server when it can), else the live map - for whoever may change the map only, when $cacheOnly (the visitor never loads the provider: an empty frame until a picture is captured), for everyone otherwise. It is glitchr/ux-google's rule (cache_only, cache_control), the provider aside.

    6 methods

  • MapRendererInterface interface

    The map in the browser: the provider turns a view into a description the page's script draws (assets/omnimap.js and the provider's driver) - plain data, no code, the same for a Twig page, a Laravel view or a React component:

    3 methods

  • ProviderFactory class

    A provider's factory fills a Config - its name ("omnimap.factory_name"), its title ("omnimap.factory_title"), the options it needs ("omnimap.required_options") and the defaults of the others - then builds the provider from it.

    3 methods

  • ProviderFactoryInterface interface

    Builds a provider from its options (a key, a secret, a tile URL...).

    2 methods

  • ProviderInterface interface

    One map provider, configured: Google, OpenStreetMap... Its Capabilities say what it can be asked - draw a map in the browser (MapRendererInterface), make an image of one on the server (StaticMapInterface), find places (GeocoderInterface), give tiles (TileSourceInterface) - and what it costs the visitor's privacy.

    3 methods

  • Registry class

    The application's map providers by name, each built once from its factory and options:

    10 methods

  • Signer class

    HMAC-SHA1 with a secret given in URL-safe base64, the signature in URL-safe base64: Google's rule for signing a Maps URL, and the rule glitchr/ux-google named its captured maps by - kept, so the pictures captured before omnimap keep their names. An empty secret signs with an empty key, as ux-google did.

    6 methods

  • StaticMapInterface interface

    A map as an image, made on the server: the provider's static map service, or tiles put together. The image carries what the provider asks to be shown on it (an attribution) when the provider does not draw it itself.

    1 method

  • TileSourceInterface interface

    Square tiles of the Web Mercator grid, one URL each: what Leaflet draws and what Static\TileStitcher puts together.

    6 methods

Omnimap\Exception

  • InvalidArgumentException class

    A value no map can hold: a latitude past a pole, a size of zero, a zoom below 0.

  • InvalidConfigException class

    A provider asked for with options it cannot work with, or not configured at all.

  • NotSupportedException class

    A provider asked for a capability it does not have: a static image of a provider that only draws in the browser.

    1 method

  • OmnimapException interface

    Every exception omnimap throws itself. A storage's own failures (Flysystem's, omnidrive's) and an HTTP client's pass through as they are.

  • ProviderException class

    The provider answered, and not with what was asked: an error status, an image that is not one.

    1 method

  • UnreachableException class

    The provider could not be reached: a network error, a timeout.

Omnimap\Geocoding

  • GeocoderPhp class

    omnimap's geocoding is geocoder-php's (willdurand/geocoder): a provider of theirs asked, its Locations turned into Places. Around it, what the providers' terms ask of whoever calls them: answers kept (a PSR-16 cache, $ttl seconds; Nominatim: "results must be cached on your side") and a pace (at least $interval seconds between two calls of this process; Nominatim: "an absolute maximum of 1 request per second" - across processes, a shared cache is what keeps the count down).

    4 methods

Omnimap\Http

  • Redaction class

    What a failed call may carry of its credentials, taken out before the failure leaves the package: an HTTP client's exception quotes the URL called (a key in its query, a password in its user part), and every exception's trace keeps the arguments of the calls under it (the request options, headers and query with the key) unless PHP runs with zend.exception_ignore_args.

    5 methods · 1 constant

Omnimap\Model

  • Address class

    What a geocoder says of a place's address; any part may be unknown.

    3 methods · 8 properties

  • Bounds class

    A box on the map: its south-west and north-east corners. A box across the antimeridian has a western longitude greater than its eastern one.

    4 methods · 2 properties

  • Image class

    An image a provider made: its bytes, its media type and its size.

    1 method · 3 properties

  • LatLng class

    A point on Earth in degrees (WGS 84): a latitude from -90 to 90, a longitude of any value (180.5 and -179.5 are the same meridian; wrapped() brings it back between -180 and 180). A map's description carries it wrapped (MapView::toArray()).

    7 methods · 2 properties

  • MapView class

    What a map shows, whoever draws it: its centre and zoom (the Web Mercator zoom every provider shares: 0 is the whole world in one 256-pixel tile), its markers, whether the provider's own controls are shown, and the options only one provider understands, under that provider's name (['google' => ['styles' => [...]]]): another provider ignores them.

    7 methods · 6 properties

  • Marker class

    A pin on the map: where, its title (shown on hover by the renderers that can), its colour (a CSS hex colour).

    3 methods · 3 properties

  • Place class

    A place a geocoder found: where it is, what it is called, its address when known, the box it covers, and who said so (the provider's name) - a provider's terms often ask that its answers be shown with its name, and some forbid showing them on another provider's map.

    3 methods · 6 properties

  • Point class

    A position in pixels: on the whole world at a zoom (Projection\WebMercator), or on an image.

    1 method · 2 properties

  • Size class

    A width and a height in pixels.

    5 methods · 2 properties

Omnimap\Projection

  • WebMercator class

    The projection of Google's, OpenStreetMap's and nearly every web map's tiles (EPSG:3857): at zoom z the world is a square of 256 x 2^z pixels, x growing eastward from the antimeridian, y southward from latitude 85.0511 (the square's edge).

    4 methods · 2 constants

Omnimap\Snapshot

  • DirectoryStorage class

    The cache in a directory of the server's disk.

    5 methods

  • DriveStorage class

    The cache on an omnidrive Drive (omnisense/omnidrive, suggested): the storage an application names ("uploads"), wherever it is - a directory, an S3 bucket, an SFTP server - Flysystem behind it.

    5 methods

  • FlysystemStorage class

    The cache in a Flysystem storage (league/flysystem 3, suggested): local, S3, SFTP... - the operator a host already has (Symfony's flysystem-bundle storages, a Laravel disk's driver).

    5 methods

  • Snapshot class

    A picture of a map, kept: its name (the signature of what it shows), its size, and the grid of square tiles it is cut into (the last row and column padded to a whole tile). metadata() is the file kept beside the tiles, written as glitchr/ux-google wrote it - the same keys and the same types, PHP-serialized - so the captures made before omnimap are read as they are.

    5 methods · 6 properties

  • SnapshotStore class

    The map pictures in a Storage, laid out as glitchr/ux-google laid them out: under $directory ("google"), one folder per signature, the tiles named by $pattern ("{signature}/image-{id}") with the format's extension, the metadata beside them:

    8 methods

  • Snapshots class

    The map cache, whatever the provider: a view is named by the signature of what its picture depends on (the renderer's fingerprint, signed), and its picture is kept in a SnapshotStore. The picture comes from the browser (an administrator's capture of the live map, save()) or from the server (make(), when a StaticMapInterface is given: the provider's static map service, or its tiles put together) - the cache does not care which.

    10 methods

  • Storage interface

    Where the map pictures are kept: the four things the cache asks of a storage. FlysystemStorage puts any Flysystem storage behind it (local, S3...), DirectoryStorage a plain directory; an application's own storage contract fits in a few lines.

    4 methods

Omnimap\Static

  • TileStitcher class

    A map image made on the server from a tile source: the tiles the view covers, fetched (all at once: the HTTP client runs them side by side) with the source's headers, kept in a PSR-16 cache as long as the server's Cache-Control allows (max-age plus stale-while-revalidate; 7 days when it says nothing - OpenStreetMap's tile policy), put together with GD, the markers drawn as dots, the attribution written in the bottom-right corner.

    3 methods

Omnimap\Testing

  • ArrayCache class

    A PSR-16 cache in this process's memory, with what was set kept readable (ttls()).

    8 methods · 1 property

  • FixedGeocoder class

    A geocoder-php provider that knows a few places by heart (and counts the questions it was asked): GeocoderPhp checked with no network.

    4 methods · 1 property

  • PlainTiles class

    Tiles drawn here, for a test or the harness's bare script: a tile of one colour per zoom, x and y, its coordinates written on it - the image a RecordedHttpClient answers with.

    2 methods

  • ProviderContractTests trait

    What every omnimap provider does, as PHPUnit tests: a provider's test case uses this trait and gives its factory, built over the HTTP client the suite hands it (the provider wraps it in a PSR-18 client for geocoder-php when it geocodes). No test reaches the network: every answer is recorded.

    8 methods

  • RecordedHttpClient class

    An HTTP client that answers from what it was given - a callable of the method, the URL and the options, returning [status, body, headers] - and keeps every request made ($requests): a provider's calls checked with no network.

    4 methods · 1 property

  • RecordedResponse class

    RecordedHttpClient's answer.

    7 methods

  • TestTiles class

    A provider for tests and the bare script: tiles from https://tiles.example/{z}/{x}/{y}.png (answer them with PlainTiles), a view described as plain data, its image made by TileStitcher.

    13 methods

Omnimap

Capabilities class

final readonly class Capabilities Capabilities.php:9

What a provider is, said before it is asked anything: what it can do, and who it makes the visitor's browser or the server talk to.

public bool $renderer

it draws a map in the browser (MapRendererInterface)

public bool $staticMap

it makes an image of a map on the server (StaticMapInterface)

public bool $geocoder

it finds places from an address and addresses from a point (GeocoderInterface)

public bool $tiles

it gives tiles, one URL per tile (TileSourceInterface)

public array $browserHosts

the hosts a visitor's browser reaches when the map is drawn live: what a consent asks about

public bool $cookies

whether its browser script sets or reads cookies

public array $terms

the terms whoever runs it must follow (URLs)

Capabilities::__construct()

public function __construct(public bool $renderer = false, public bool $staticMap = false, public bool $geocoder = false, public bool $tiles = false, public array $browserHosts = [], public bool $cookies = false, public array $terms = [])
$renderer

it draws a map in the browser (MapRendererInterface)

$staticMap

it makes an image of a map on the server (StaticMapInterface)

$geocoder

it finds places from an address and addresses from a point (GeocoderInterface)

$tiles

it gives tiles, one URL per tile (TileSourceInterface)

$browserHosts

the hosts a visitor's browser reaches when the map is drawn live: what a consent asks about

$cookies

whether its browser script sets or reads cookies

$terms

the terms whoever runs it must follow (URLs)

Capabilities::contracts()

public function contracts(): array
Returns

what it can be asked, by contract: renderer, staticMap, geocoder, tiles

Capabilities::toArray()

public function toArray(): array

Config class

final class Config extends ArrayObject Config.php:14

A provider's configuration while its factory builds it: the options given, the factory's defaults under them, and the keys that must be filled.

Config::defaults()

public function defaults(array $defaults): self

Sets each key not set yet.

Config::validateNotEmpty()

public function validateNotEmpty(array $keys): void

Config::get()

public function get(string $key, mixed $default = null): mixed

Config::string()

public function string(string $key): ?string

A string option; null when it is empty.

Config::int()

public function int(string $key, int $default = 0): int

Config::float()

public function float(string $key, float $default = 0.0): float

Config::bool()

public function bool(string $key): bool

A boolean option, as an environment variable gives it too: "1", "true", "yes", "on".

GeocoderInterface interface

interface GeocoderInterface extends ProviderInterface GeocoderInterface.php:14

Places from an address, addresses from a point. omnimap does not geocode itself: Geocoding\GeocoderPhp asks a geocoder-php provider (willdurand/geocoder), with a cache and the pace the provider's terms set.

GeocoderInterface::geocode()

public function geocode(string $address, ?string $locale = null, int $limit = 5): array
Returns

the best first; none found, an empty list

GeocoderInterface::reverse()

public function reverse(LatLng $position, ?string $locale = null, int $limit = 5): array

MapHtml class

final class MapHtml MapHtml.php:20

The map's element, as any host prints it (Twig, Blade, a React server render, plain PHP): either the picture kept in the cache, cut in tiles that assets/snapshot.js lays out, or a live map that assets/omnimap.js draws from the renderer's description.

The picture's markup takes the host's own names where it has older ones to keep (lesringostars: class "google-tilemap", id "myMap_html2canvas", src "/google/{signature}/{id}.webp"). Options: class, suffix (of the frame's id), src (the tiles' address), missing (the address of a picture snapshot.js shows over a frame with no picture kept and in place of a tile that does not load; '' for none).

MapHtml::__construct()

public function __construct(array $options = [])

MapHtml::snapshot()

public function snapshot(string $id, string $signature, ?Snapshot $snapshot, string $attribution = ''): string

The picture of a map: the element $id, the tiles' frame in it, and the attribution the provider asks for. No snapshot yet: the frame with no tile (nothing is shown, nothing is fetched).

MapHtml::live()

public function live(string $id, array $description): string

A live map: the element $id carrying the renderer's description, which assets/omnimap.js draws (mountAll()) once the provider's script may be loaded.

MapHtml::button()

public function button(string $action, string $id, string $url, string $token, string $contents, array $attributes = []): string

MapPrinter class

final class MapPrinter MapPrinter.php:21

What a page shows of a view, whatever the host: the picture kept in the cache when there is one (made now by the server when it can), else the live map - for whoever may change the map only, when $cacheOnly (the visitor never loads the provider: an empty frame until a picture is captured), for everyone otherwise. It is glitchr/ux-google's rule (cache_only, cache_control), the provider aside.

The host gives what it alone knows: whether the visitor may change the map, and the export and suppress URLs and token (omnibridge's Twig extension asks its Access, Urls and Tokens).

MapPrinter::__construct()

public function __construct(readonly Snapshots $snapshots, readonly MapHtml $html = new MapHtml(), readonly bool $cacheOnly = true, ?\Closure $onError = null)
$onError

what to do with a picture the server could not make (log it): the page shows no picture

MapPrinter::map()

public function map(MapView $view, bool $mayChange = false): string

MapPrinter::exportButton()

public function exportButton(MapView $view, bool $mayChange, string $url, string $token, string $contents, array $attributes = []): string

The button that sends the live map's picture to the cache: for whoever may change the map, whether a picture is kept or not - a kept one is replaced by the next capture (glitchr/ux-google's "update the map"; lesringostars shows it beside the delete button over a kept picture).

MapPrinter::suppressButton()

public function suppressButton(MapView $view, bool $mayChange, string $url, string $token, string $contents, array $attributes = []): string

The button that deletes the picture kept: for whoever may change the map, when there is a picture.

MapPrinter::signature()

public function signature(MapView $view): string

MapPrinter::snapshots()

public function snapshots(): Snapshots

MapRendererInterface interface

interface MapRendererInterface extends ProviderInterface MapRendererInterface.php:19

The map in the browser: the provider turns a view into a description the page's script draws (assets/omnimap.js and the provider's driver) - plain data, no code, the same for a Twig page, a Laravel view or a React component:

{"provider": "google", "view": {...MapView::toArray()}, "library": {...what the driver loads}, "options": {...}}

A renderer also says what a picture of the view depends on (fingerprint()): a captured image of the map (Snapshot) is named by it, signed, so a change of centre, zoom or provider makes a new one.

MapRendererInterface::describe()

public function describe(MapView $view): array
Returns

JSON-ready

MapRendererInterface::fingerprint()

public function fingerprint(MapView $view): string

The text a picture of this view is named after, once signed (Signer).

MapRendererInterface::attribution()

public function attribution(): string

The attribution the map must show, as HTML (the provider's terms ask for it).

ProviderFactory class

abstract class ProviderFactory implements ProviderFactoryInterface ProviderFactory.php:15

A provider's factory fills a Config - its name ("omnimap.factory_name"), its title ("omnimap.factory_title"), the options it needs ("omnimap.required_options") and the defaults of the others - then builds the provider from it.

Nothing here calls anything: a factory whose provider is reached over HTTP takes its client in its own constructor - the application's, a MockHttpClient in a test.

ProviderFactory::getName()

public function getName(): string

ProviderFactory::create()

public function create(array $options = []): ProviderInterface

ProviderFactory::createConfig()

public function createConfig(array $options = []): Config

ProviderFactoryInterface interface

interface ProviderFactoryInterface ProviderFactoryInterface.php:6

Builds a provider from its options (a key, a secret, a tile URL...).

ProviderFactoryInterface::getName()

public function getName(): string

The name providers are configured with: "google", "openstreetmap".

..

ProviderFactoryInterface::create()

public function create(array $options = []): ProviderInterface

ProviderInterface interface

interface ProviderInterface ProviderInterface.php:12

One map provider, configured: Google, OpenStreetMap... Its Capabilities say what it can be asked - draw a map in the browser (MapRendererInterface), make an image of one on the server (StaticMapInterface), find places (GeocoderInterface), give tiles (TileSourceInterface) - and what it costs the visitor's privacy.

ProviderInterface::getName()

public function getName(): string

The factory's name: "google", "openstreetmap".

..

ProviderInterface::getTitle()

public function getTitle(): string

ProviderInterface::capabilities()

public function capabilities(): Capabilities

Registry class

final class Registry Registry.php:20

The application's map providers by name, each built once from its factory and options:

$registry = new Registry([new GoogleFactory($http), new OpenStreetMapFactory($http)], [ 'maps' => ['factory' => 'openstreetmap', 'options' => ['user_agent' => 'MySite/1.0 (+https://example.org)']], 'places' => ['factory' => 'google', 'options' => ['api_key' => '...']], ]);

$registry->renderer('maps')->describe($view); $registry->geocoder('places')->geocode('Kyoto');

Registry::__construct()

public function __construct(iterable $factories, readonly array $config)

Registry::get()

public function get(string $name): ProviderInterface

Registry::has()

public function has(string $name): bool

Registry::renderer()

public function renderer(string $name): MapRendererInterface

The provider, as a map drawn in the browser.

Registry::staticMap()

public function staticMap(string $name): StaticMapInterface

The provider, as a map image made on the server.

Registry::geocoder()

public function geocoder(string $name): GeocoderInterface

The provider, as a geocoder.

Registry::tiles()

public function tiles(string $name): TileSourceInterface

The provider, as tiles.

Registry::options()

public function options(string $name): array
Returns

the options a provider is configured with

Registry::names()

public function names(): array
Returns

the configured providers' names

Registry::factories()

public function factories(): array
Returns

the factories installed: what factory: may name

Signer class

final class Signer Signer.php:12

HMAC-SHA1 with a secret given in URL-safe base64, the signature in URL-safe base64: Google's rule for signing a Maps URL, and the rule glitchr/ux-google named its captured maps by - kept, so the pictures captured before omnimap keep their names. An empty secret signs with an empty key, as ux-google did.

Signer::__construct()

public function __construct(readonly ?string $secret)

Signer::sign()

public function sign(string $payload): string

The signature, without base64's "=" padding (ux-google's names).

Signer::signPadded()

public function signPadded(string $payload): string

The signature with its padding: what Google expects in a URL's signature=.

Signer::verify()

public function verify(string $payload, string $signature): bool

Signer::encode()

public static function encode(string $bytes): string

Signer::decode()

public static function decode(string $text): string

StaticMapInterface interface

interface StaticMapInterface extends ProviderInterface StaticMapInterface.php:14

A map as an image, made on the server: the provider's static map service, or tiles put together. The image carries what the provider asks to be shown on it (an attribution) when the provider does not draw it itself.

StaticMapInterface::image()

public function image(MapView $view, Size $size, int $scale = 1): Image
$scale

1, or 2 for a screen of twice the density: the image is $size x $scale pixels

TileSourceInterface interface

interface TileSourceInterface extends ProviderInterface TileSourceInterface.php:9

Square tiles of the Web Mercator grid, one URL each: what Leaflet draws and what Static\TileStitcher puts together.

TileSourceInterface::template()

public function template(): string

The URL template, {z}/{x}/{y} in it: the browser's library fills it.

TileSourceInterface::url()

public function url(int $zoom, int $x, int $y): string

TileSourceInterface::tileSize()

public function tileSize(): int

In pixels: 256 nearly always.

TileSourceInterface::maxZoom()

public function maxZoom(): int

TileSourceInterface::attribution()

public function attribution(): string

As HTML.

TileSourceInterface::headers()

public function headers(): array

The headers a request for a tile must carry (a User-Agent naming the application, say).

Omnimap\Exception

InvalidArgumentException class

final class InvalidArgumentException extends InvalidArgumentException implements OmnimapException InvalidArgumentException.php:6

A value no map can hold: a latitude past a pole, a size of zero, a zoom below 0.

InvalidConfigException class

final class InvalidConfigException extends InvalidArgumentException implements OmnimapException InvalidConfigException.php:6

A provider asked for with options it cannot work with, or not configured at all.

NotSupportedException class

final class NotSupportedException extends LogicException implements OmnimapException NotSupportedException.php:6

A provider asked for a capability it does not have: a static image of a provider that only draws in the browser.

NotSupportedException::capability()

public static function capability(object $provider, string $name, string $capability): self

OmnimapException interface

interface OmnimapException extends Throwable OmnimapException.php:9

Every exception omnimap throws itself. A storage's own failures (Flysystem's, omnidrive's) and an HTTP client's pass through as they are.

ProviderException class

final class ProviderException extends RuntimeException implements OmnimapException ProviderException.php:6

The provider answered, and not with what was asked: an error status, an image that is not one.

ProviderException::answered()

public static function answered(string $provider, string $what, int|string $status): self

UnreachableException class

final class UnreachableException extends RuntimeException implements OmnimapException UnreachableException.php:6

The provider could not be reached: a network error, a timeout.

Omnimap\Geocoding

GeocoderPhp class

final class GeocoderPhp GeocoderPhp.php:28

omnimap's geocoding is geocoder-php's (willdurand/geocoder): a provider of theirs asked, its Locations turned into Places. Around it, what the providers' terms ask of whoever calls them: answers kept (a PSR-16 cache, $ttl seconds; Nominatim: "results must be cached on your side") and a pace (at least $interval seconds between two calls of this process; Nominatim: "an absolute maximum of 1 request per second" - across processes, a shared cache is what keeps the count down).

GeocoderPhp::__construct()

public function __construct(readonly Provider $provider, readonly ?CacheInterface $cache = null, readonly int $ttl = 2592000, readonly float $interval = 0.0)

GeocoderPhp::geocode()

public function geocode(string $address, ?string $locale = null, int $limit = 5): array

GeocoderPhp::reverse()

public function reverse(LatLng $position, ?string $locale = null, int $limit = 5): array

GeocoderPhp::place()

public static function place(Location $location): ?Place

Omnimap\Http

Redaction class

final class Redaction Redaction.php:22

What a failed call may carry of its credentials, taken out before the failure leaves the package: an HTTP client's exception quotes the URL called (a key in its query, a password in its user part), and every exception's trace keeps the arguments of the calls under it (the request options, headers and query with the key) unless PHP runs with zend.exception_ignore_args.

copy() gives the previous exception to wrap instead of the client's own: the same class and code, its message with the key's parameters, the user part and every secret value replaced by ***, its trace without arguments, its own previous copied the same way. Properties of the client's class beyond those of \Exception are not copied (a Symfony HttpException's response, a PSR-18 exception's request: their URL holds the key). withoutArguments() takes the arguments out of the trace of the exception thrown in its place.

const MASK = '***'

Redaction::secrets()

public static function secrets(string $url, array $options = []): array

The secrets a request carries: the values of its query parameters, headers and body fields named as credentials (key, token, secret, password, signature, auth...), a bearer token, a basic password, the URL's user part.

$options

the HTTP client's options

Redaction::sensitive()

public static function sensitive(string $name): bool

Whether a parameter, header or field of this name holds a credential.

Redaction::text()

public static function text(string $text, array $secrets = []): string

A text without credentials: in every address, the user part and the parameters named as credentials masked (api_key=***); then every secret given, raw or URL-encoded, masked wherever it stands.

Redaction::copy()

public static function copy(\Throwable $failure, array $secrets = []): \Throwable

A copy of a failure to wrap in its place: its class, code, file and line, its message through text(), its trace without arguments, its previous copied the same way.

Redaction::withoutArguments()

public static function withoutArguments(\Throwable $failure): \Throwable

The failure given, the arguments out of its trace (and out of its previous ones'), as zend.exception_ignore_args would have left it.

Omnimap\Model

Address class

final readonly class Address implements JsonSerializable Address.php:6

What a geocoder says of a place's address; any part may be unknown.

public ?string $streetNumber
public ?string $streetName
public ?string $postalCode
public ?string $locality
public ?string $subLocality
public ?string $region
public ?string $country
public ?string $countryCode

Address::__construct()

public function __construct(public ?string $streetNumber = null, public ?string $streetName = null, public ?string $postalCode = null, public ?string $locality = null, public ?string $subLocality = null, public ?string $region = null, public ?string $country = null, public ?string $countryCode = null)

Address::toArray()

public function toArray(): array

Address::jsonSerialize()

public function jsonSerialize(): array

Bounds class

final readonly class Bounds implements JsonSerializable Bounds.php:9

A box on the map: its south-west and north-east corners. A box across the antimeridian has a western longitude greater than its eastern one.

public LatLng $southWest
public LatLng $northEast

Bounds::__construct()

public function __construct(public LatLng $southWest, public LatLng $northEast)

Bounds::contains()

public function contains(LatLng $point): bool

Bounds::toArray()

public function toArray(): array

Bounds::jsonSerialize()

public function jsonSerialize(): array

Image class

final readonly class Image Image.php:6

An image a provider made: its bytes, its media type and its size.

public string $bytes
public string $mimeType
public Size $size

Image::__construct()

public function __construct(public string $bytes, public string $mimeType, public Size $size)

LatLng class

final readonly class LatLng implements JsonSerializable, Stringable LatLng.php:13

A point on Earth in degrees (WGS 84): a latitude from -90 to 90, a longitude of any value (180.5 and -179.5 are the same meridian; wrapped() brings it back between -180 and 180). A map's description carries it wrapped (MapView::toArray()).

public float $lat
public float $lng

LatLng::__construct()

public function __construct(public float $lat, public float $lng)

LatLng::fromArray()

public static function fromArray(array $array): self

LatLng::wrapped()

public function wrapped(): self

The same point, its longitude between -180 (included) and 180 (excluded).

LatLng::equals()

public function equals(self $other, float $tolerance = 1.0E-9): bool

LatLng::toArray()

public function toArray(): array

LatLng::jsonSerialize()

public function jsonSerialize(): array

LatLng::__toString()

public function __toString(): string

"lat,lng", as URLs and geocoders write a point.

MapView class

final readonly class MapView implements JsonSerializable MapView.php:16

What a map shows, whoever draws it: its centre and zoom (the Web Mercator zoom every provider shares: 0 is the whole world in one 256-pixel tile), its markers, whether the provider's own controls are shown, and the options only one provider understands, under that provider's name (['google' => ['styles' => [...]]]): another provider ignores them.

The id is the page element's the map is drawn into.

public LatLng $center
public int $zoom
public array $markers
public bool $controls
public array $options
public string $id

MapView::__construct()

public function __construct(public LatLng $center, public int $zoom, public array $markers = [], public bool $controls = true, public array $options = [], public string $id = 'map')

MapView::withMarker()

public function withMarker(Marker $marker): self

MapView::withMarkers()

public function withMarkers(array $markers): self

MapView::withOptions()

public function withOptions(string $provider, array $options): self
$options

merged over the provider's options already set

MapView::options()

public function options(string $provider): array
Returns

the options of one provider

MapView::toArray()

public function toArray(): array
Returns

the view as a description carries it: every longitude wrapped between -180 and 180

MapView::jsonSerialize()

public function jsonSerialize(): array

Marker class

final readonly class Marker implements JsonSerializable Marker.php:6

A pin on the map: where, its title (shown on hover by the renderers that can), its colour (a CSS hex colour).

public LatLng $position
public ?string $title
public ?string $color

Marker::__construct()

public function __construct(public LatLng $position, public ?string $title = null, public ?string $color = null)

Marker::toArray()

public function toArray(): array

Marker::jsonSerialize()

public function jsonSerialize(): array

Place class

final readonly class Place implements JsonSerializable Place.php:11

A place a geocoder found: where it is, what it is called, its address when known, the box it covers, and who said so (the provider's name) - a provider's terms often ask that its answers be shown with its name, and some forbid showing them on another provider's map.

public LatLng $position
public string $label
public string $providedBy
public ?Address $address
public ?Bounds $bounds
public ?string $id

Place::__construct()

public function __construct(public LatLng $position, public string $label, public string $providedBy, public ?Address $address = null, public ?Bounds $bounds = null, public ?string $id = null)

Place::toArray()

public function toArray(): array

Place::jsonSerialize()

public function jsonSerialize(): array

Point class

final readonly class Point Point.php:6

A position in pixels: on the whole world at a zoom (Projection\WebMercator), or on an image.

public float $x
public float $y

Point::__construct()

public function __construct(public float $x, public float $y)

Size class

final readonly class Size implements JsonSerializable, Stringable Size.php:8

A width and a height in pixels.

public int $width
public int $height

Size::__construct()

public function __construct(public int $width, public int $height)

Size::fromString()

public static function fromString(string $size): self

"640x480"

Size::scaled()

public function scaled(int $scale): self

Size::jsonSerialize()

public function jsonSerialize(): array

Size::__toString()

public function __toString(): string

Omnimap\Projection

WebMercator class

final class WebMercator WebMercator.php:16

The projection of Google's, OpenStreetMap's and nearly every web map's tiles (EPSG:3857): at zoom z the world is a square of 256 x 2^z pixels, x growing eastward from the antimeridian, y southward from latitude 85.0511 (the square's edge).

const TILE = 256
const MAX_LATITUDE = 85.0511287798066

WebMercator::worldSize()

public static function worldSize(float $zoom): float

The world's width at a zoom, in pixels.

WebMercator::point()

public static function point(LatLng $latLng, float $zoom): Point

Where a point lies on the world at a zoom, in pixels.

WebMercator::latLng()

public static function latLng(Point $point, float $zoom): LatLng

The point at a position on the world at a zoom (its longitude not wrapped).

WebMercator::bounds()

public static function bounds(LatLng $center, int $zoom, Size $size): Bounds

The box an image of this size shows around this centre at this zoom.

Omnimap\Snapshot

DirectoryStorage class

final class DirectoryStorage implements Storage DirectoryStorage.php:8

The cache in a directory of the server's disk.

DirectoryStorage::__construct()

public function __construct(string $root)

DirectoryStorage::read()

public function read(string $path): ?string

DirectoryStorage::write()

public function write(string $path, string $contents): void

DirectoryStorage::exists()

public function exists(string $path): bool

DirectoryStorage::deleteDirectory()

public function deleteDirectory(string $path): void

DriveStorage class

final class DriveStorage implements Storage DriveStorage.php:15

The cache on an omnidrive Drive (omnisense/omnidrive, suggested): the storage an application names ("uploads"), wherever it is - a directory, an S3 bucket, an SFTP server - Flysystem behind it.

DriveStorage::__construct()

public function __construct(readonly Drive $drive)

DriveStorage::read()

public function read(string $path): ?string

DriveStorage::write()

public function write(string $path, string $contents): void

DriveStorage::exists()

public function exists(string $path): bool

DriveStorage::deleteDirectory()

public function deleteDirectory(string $path): void

FlysystemStorage class

final class FlysystemStorage implements Storage FlysystemStorage.php:16

The cache in a Flysystem storage (league/flysystem 3, suggested): local, S3, SFTP... - the operator a host already has (Symfony's flysystem-bundle storages, a Laravel disk's driver).

FlysystemStorage::__construct()

public function __construct(readonly FilesystemOperator $filesystem)

FlysystemStorage::read()

public function read(string $path): ?string

FlysystemStorage::write()

public function write(string $path, string $contents): void
Throws

FilesystemException

FlysystemStorage::exists()

public function exists(string $path): bool

FlysystemStorage::deleteDirectory()

public function deleteDirectory(string $path): void
Throws

FilesystemException

Snapshot class

final readonly class Snapshot implements JsonSerializable Snapshot.php:13

A picture of a map, kept: its name (the signature of what it shows), its size, and the grid of square tiles it is cut into (the last row and column padded to a whole tile). metadata() is the file kept beside the tiles, written as glitchr/ux-google wrote it - the same keys and the same types, PHP-serialized - so the captures made before omnimap are read as they are.

public string $signature
public int $width
public int $height
public ?int $tilesize
public int $xtiles
public int $ytiles

Snapshot::__construct()

public function __construct(public string $signature, public int $width, public int $height, public ?int $tilesize, public int $xtiles, public int $ytiles)

Snapshot::fromMetadata()

public static function fromMetadata(string $signature, array $metadata): ?self

Snapshot::metadata()

public function metadata(): array

Snapshot::tiles()

public function tiles(): int

Snapshot::jsonSerialize()

public function jsonSerialize(): array

SnapshotStore class

final class SnapshotStore SnapshotStore.php:21

The map pictures in a Storage, laid out as glitchr/ux-google laid them out: under $directory ("google"), one folder per signature, the tiles named by $pattern ("{signature}/image-{id}") with the format's extension, the metadata beside them:

google/tcIj2DZnhR2xGsZ8K8t2ID4PKVg/image-0.png ... image-23.png google/tcIj2DZnhR2xGsZ8K8t2ID4PKVg/metadata.txt

save() cuts an image into tiles (GD) - a picture the browser captured, or one the server made (Snapshots::make()). What has been asked during this object's life is remembered (one storage round trip per question: on S3 each is an HTTP request); save() and delete() forget it.

SnapshotStore::__construct()

public function __construct(readonly Storage $storage, readonly string $directory = 'omnimap', readonly string $pattern = '{signature}/image-{id}', readonly string $format = 'png')

SnapshotStore::find()

public function find(string $signature): ?Snapshot

SnapshotStore::tile()

public function tile(string $signature, int $id): ?string

A tile's bytes, in the store's format; null when there is none.

SnapshotStore::save()

public function save(string $signature, string $image, ?int $tilesize = 512): Snapshot

Keeps an image as the picture of $signature: cut into squares of $tilesize (the last row and column padded with transparency), or whole when $tilesize is null. Replaces what was kept under that name.

SnapshotStore::delete()

public function delete(string $signature): void

Forgets the picture of $signature, tiles and metadata.

SnapshotStore::format()

public function format(): string

SnapshotStore::tilePath()

public function tilePath(string $signature, int $id): string

SnapshotStore::metadataPath()

public function metadataPath(string $signature): string

Snapshots class

final class Snapshots Snapshots.php:23

The map cache, whatever the provider: a view is named by the signature of what its picture depends on (the renderer's fingerprint, signed), and its picture is kept in a SnapshotStore. The picture comes from the browser (an administrator's capture of the live map, save()) or from the server (make(), when a StaticMapInterface is given: the provider's static map service, or its tiles put together) - the cache does not care which.

$snapshots = new Snapshots($renderer, new Signer($secret), new SnapshotStore(new DirectoryStorage('/var/maps')), $staticMap); $snapshot = $snapshots->findOrMake($view); // made once, then read

Snapshots::__construct()

public function __construct(readonly MapRendererInterface $renderer, readonly Signer $signer, readonly SnapshotStore $store, readonly ?StaticMapInterface $staticMap = null, readonly Size $size = new Size(1512, 938), readonly int $scale = 1, readonly ?int $tilesize = 512)

Snapshots::signature()

public function signature(MapView $view): string

Snapshots::find()

public function find(MapView $view): ?Snapshot

Snapshots::canMake()

public function canMake(): bool

Whether the server can make a picture itself (a static map is configured).

Snapshots::make()

public function make(MapView $view): Snapshot

The picture of the view, made now by the server and kept (replacing any).

Snapshots::findOrMake()

public function findOrMake(MapView $view): ?Snapshot

The picture kept; made now when there is none and the server can make one.

Snapshots::save()

public function save(string $signature, string $image, ?int $tilesize = null): Snapshot

A picture the browser captured (an image's bytes, or a data: URL), kept under its signature.

Snapshots::delete()

public function delete(string $signature): void

Snapshots::store()

public function store(): SnapshotStore

Snapshots::renderer()

public function renderer(): MapRendererInterface

Storage interface

interface Storage Storage.php:13

Where the map pictures are kept: the four things the cache asks of a storage. FlysystemStorage puts any Flysystem storage behind it (local, S3...), DirectoryStorage a plain directory; an application's own storage contract fits in a few lines.

Paths are relative, "/"-separated: "google/<signature>/image-0.png".

Storage::read()

public function read(string $path): ?string

The file's contents; null when there is no such file.

Storage::write()

public function write(string $path, string $contents): void

Storage::exists()

public function exists(string $path): bool

Storage::deleteDirectory()

public function deleteDirectory(string $path): void

The directory and everything in it; nothing when it is not there.

Omnimap\Static

TileStitcher class

final class TileStitcher TileStitcher.php:35

A map image made on the server from a tile source: the tiles the view covers, fetched (all at once: the HTTP client runs them side by side) with the source's headers, kept in a PSR-16 cache as long as the server's Cache-Control allows (max-age plus stale-while-revalidate; 7 days when it says nothing - OpenStreetMap's tile policy), put together with GD, the markers drawn as dots, the attribution written in the bottom-right corner.

The world repeats east and west; above and below it, $background.

A scale of 2 takes the tiles of the next zoom: the same view at twice the density.

The view's zoom is the one every provider shares (0: the world in 256 pixels). A source of 512-pixel tiles numbers them as such servers do, 2^z a side at z (Leaflet's zoomOffset -1): the view's zoom z is read at the source's zoom z - 1, and at zoom 0 the source's one tile is drawn at half its size.

TileStitcher::__construct()

public function __construct(readonly TileSourceInterface $tiles, readonly HttpClientInterface $http, readonly ?CacheInterface $cache = null, readonly string $background = '#aad3df', readonly string $markerColor = '#d33b3b')

TileStitcher::image()

public function image(MapView $view, Size $size, int $scale = 1): Image

TileStitcher::lifetime()

public static function lifetime(string $cacheControl): int

max-age plus stale-while-revalidate, in seconds; 7 days when the server says neither.

Omnimap\Testing

ArrayCache class

final class ArrayCache implements CacheInterface ArrayCache.php:8

A PSR-16 cache in this process's memory, with what was set kept readable (ttls()).

public array $ttls = []

ArrayCache::get()

public function get(string $key, mixed $default = null): mixed

ArrayCache::set()

public function set(string $key, mixed $value, \DateInterval|int|null $ttl = null): bool

ArrayCache::delete()

public function delete(string $key): bool

ArrayCache::clear()

public function clear(): bool

ArrayCache::getMultiple()

public function getMultiple(iterable $keys, mixed $default = null): iterable
$keys

@return iterable<string, mixed>

ArrayCache::setMultiple()

public function setMultiple(iterable $values, \DateInterval|int|null $ttl = null): bool

ArrayCache::deleteMultiple()

public function deleteMultiple(iterable $keys): bool

ArrayCache::has()

public function has(string $key): bool

FixedGeocoder class

final class FixedGeocoder implements Provider FixedGeocoder.php:16

A geocoder-php provider that knows a few places by heart (and counts the questions it was asked): GeocoderPhp checked with no network.

public int $calls = 0

FixedGeocoder::__construct()

public function __construct(readonly array $places)

FixedGeocoder::geocodeQuery()

public function geocodeQuery(GeocodeQuery $query): Collection

FixedGeocoder::reverseQuery()

public function reverseQuery(ReverseQuery $query): Collection

FixedGeocoder::getName()

public function getName(): string

PlainTiles class

final class PlainTiles PlainTiles.php:10

Tiles drawn here, for a test or the harness's bare script: a tile of one colour per zoom, x and y, its coordinates written on it - the image a RecordedHttpClient answers with.

PlainTiles::png()

public static function png(int $zoom, int $x, int $y, int $size = 256): string

PlainTiles::answer()

public static function answer(int $size = 256): \Closure

The answer RecordedHttpClient gives for ".../{z}/{x}/{y}.png": tiles of $size pixels.

ProviderContractTests trait

trait ProviderContractTests ProviderContractTests.php:62

What every omnimap provider does, as PHPUnit tests: a provider's test case uses this trait and gives its factory, built over the HTTP client the suite hands it (the provider wraps it in a PSR-18 client for geocoder-php when it geocodes). No test reaches the network: every answer is recorded.

final class OpenStreetMapContractTest extends TestCase { use ProviderContractTests;

protected function contractFactory(?HttpClientInterface $http): ProviderFactoryInterface
{
    return new OpenStreetMapFactory($http, $http ? new Psr18Client($http) : null, new ArrayCache());
}
    protected function contractOptions(): array { return ['user_agent' => 'tests/1.0', 'nominatim_interval' => 0]; }
}

What it checks: - the factory's name is the provider's, the Registry builds it from {factory, options} once; a missing required option is refused with InvalidConfigException naming it; - capabilities() says exactly what the provider answers: a declared contract is implemented, an implemented one declared off (no client given) throws NotSupportedException, never a TypeError; browser hosts are host names, terms are https addresses; - a renderer's description is plain data (JSON and back) naming the provider, the view and the consent; every address in it is on a declared browser host; its fingerprint is stable and follows the centre, the zoom and the markers; - a static map is an image: bytes that are the media type it says, no larger than asked; - a tile source's addresses are complete https URLs, its sizes and zooms sane; - a geocoder's places are places of this provider, within the limit, on the globe; - errors are the family's: an answer other than 200 or a body that is not what was asked is a ProviderException, a transport failure an UnreachableException.

Requires phpunit/phpunit and symfony/http-client (the provider's require-dev).

ProviderContractTests::testTheFactoryNamesWhatItBuildsAndTheRegistryBuildsItOnce()

public function testTheFactoryNamesWhatItBuildsAndTheRegistryBuildsItOnce(): void

ProviderContractTests::testAMissingRequiredOptionIsRefusedByName()

public function testAMissingRequiredOptionIsRefusedByName(): void

ProviderContractTests::testCapabilitiesAreWhatTheProviderAnswers()

public function testCapabilitiesAreWhatTheProviderAnswers(): void

ProviderContractTests::testARendererDescribesTheViewAsPlainData()

public function testARendererDescribesTheViewAsPlainData(): void

ProviderContractTests::testAStaticMapIsAnImageOfTheSizeAsked()

public function testAStaticMapIsAnImageOfTheSizeAsked(): void

ProviderContractTests::testTileAddressesAreComplete()

public function testTileAddressesAreComplete(): void

ProviderContractTests::testAGeocoderAnswersPlacesOfItsOwn()

public function testAGeocoderAnswersPlacesOfItsOwn(): void

ProviderContractTests::testErrorsAreTheFamilysExceptions()

public function testErrorsAreTheFamilysExceptions(): void

RecordedHttpClient class

final class RecordedHttpClient implements HttpClientInterface RecordedHttpClient.php:15

An HTTP client that answers from what it was given - a callable of the method, the URL and the options, returning [status, body, headers] - and keeps every request made ($requests): a provider's calls checked with no network.

public array $requests = []

RecordedHttpClient::__construct()

public function __construct(readonly \Closure $answer)

RecordedHttpClient::request()

public function request(string $method, string $url, array $options = []): ResponseInterface

RecordedHttpClient::stream()

public function stream(ResponseInterface|iterable $responses, ?float $timeout = null): ResponseStreamInterface

RecordedHttpClient::withOptions()

public function withOptions(array $options): static

RecordedResponse class

final class RecordedResponse implements ResponseInterface RecordedResponse.php:8

RecordedHttpClient's answer.

RecordedResponse::__construct()

public function __construct(readonly int $status, readonly string $body, readonly array $headers, readonly string $url)

RecordedResponse::getStatusCode()

public function getStatusCode(): int

RecordedResponse::getHeaders()

public function getHeaders(bool $throw = true): array

RecordedResponse::getContent()

public function getContent(bool $throw = true): string

RecordedResponse::toArray()

public function toArray(bool $throw = true): array

RecordedResponse::cancel()

public function cancel(): void

RecordedResponse::getInfo()

public function getInfo(?string $type = null): mixed

TestTiles class

final class TestTiles implements MapRendererInterface, StaticMapInterface, TileSourceInterface TestTiles.php:21

A provider for tests and the bare script: tiles from https://tiles.example/{z}/{x}/{y}.png (answer them with PlainTiles), a view described as plain data, its image made by TileStitcher.

TestTiles::__construct()

public function __construct(readonly HttpClientInterface $http, readonly ?CacheInterface $cache = null, readonly int $tileSize = 256)
$tileSize

256, or 512 for a source of 512-pixel tiles (2^z a side at z)

TestTiles::getName()

public function getName(): string

TestTiles::getTitle()

public function getTitle(): string

TestTiles::capabilities()

public function capabilities(): Capabilities

TestTiles::describe()

public function describe(MapView $view): array

TestTiles::fingerprint()

public function fingerprint(MapView $view): string

TestTiles::attribution()

public function attribution(): string

TestTiles::image()

public function image(MapView $view, Size $size, int $scale = 1): Image

TestTiles::template()

public function template(): string

TestTiles::url()

public function url(int $zoom, int $x, int $y): string

TestTiles::tileSize()

public function tileSize(): int

TestTiles::maxZoom()

public function maxZoom(): int

TestTiles::headers()

public function headers(): array