Read from the package's own PHP files at the commit 8be4dc647fc0: 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.
ConfigclassA catalogue's configuration while its factory builds it: the options given, the factory's defaults under them, and the keys that must be filled.
3 methods
PlatformenumWhere a recording can be listened to or bought. The label comes first: a site shows "released by ES-DUR, buy it there" before "listen on Spotify". rank() orders a PlatformLinks; fromOdesli() maps song.link's keys; embeddable() says whether Player\Embedder knows an iframe for it.
5 methods · 24 cases
RegistryclassThe catalogues by name, each built once from its factory and options:
6 methods
OmnisongBundleclassOmnisong in a Symfony application: the catalogue packages installed (omnisong/odesli, omnisong/itunes) registered, the catalogues built from configuration and asked in that order by the one CatalogInterface that is autowired, the Embedder with the site's theme, and the Twig functions:
3 methods
OmnisongExtensionclassThe players and the platforms' names in a template:
6 methods
CatalogclassEvery configured catalogue asked in turn, their answers merged: Odesli gives the links, iTunes the tracks and their previews, and the label the site knows goes first. What one catalogue cannot do the next does; a catalogue that is down is skipped, and remembered as skipped so the caller does not cache a half answer (see $incomplete).
6 methods · 1 property
CatalogFactoryclassThe Omnibus way, at its simplest: a catalogue's factory fills a Config - its name ("omnisong.factory_name"), the options it needs ("omnisong.required_options") and their defaults - then builds the catalogue from it, on the application's HTTP client when one is given.
4 methods
CatalogFactoryInterfaceinterfaceBuilds a catalogue from its options (a key, a country...).
2 methods
CatalogInterfaceinterfaceA service that knows recordings: where they are (the links), what they are (a release with its tracks and previews), what an artist put out.
4 methods
InvalidConfigExceptionclassA catalogue misconfigured: a key missing, an unknown factory.
InvalidReferenceExceptionclassA value Reference::parse() cannot read: neither a URL, a UPC/EAN nor an ISRC.
NotSupportedExceptionclassThe catalogue does not read that kind of reference, or does not do that at all.
2 methods
OmnisongExceptioninterfaceEvery exception Omnisong throws.
ProviderExceptionclassThe catalogue's service answered with an error.
1 method · 2 properties
RateLimitedExceptionclassThe service asks to slow down (Odesli: 10 requests a minute without a key).
1 method · 1 property
UnavailableExceptionclassThe service could not be reached, or is down: never "not found". A caller that caches an answer must not cache this one.
RedactionclassWhat 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
ArtistclassA performer as a catalogue names it, with its ids on the platforms that gave one.
1 method · 4 properties
EmbedclassAn iframe that plays from a platform: its markup, its size, where it loads from (for a CSP).
1 method · 5 properties
LabelclassThe label a release came out on: who to show first, and where its shop is.
1 method · 3 properties
PlatformLinkclassOne place the recording is: the platform, the URL, the platform's own id when known.
2 methods · 5 properties
PlatformLinksclassThe links of one recording, one per platform, in the order a site shows them: the label first, then the shops, then the streamers (Platform::rank()).
14 methods
ReferenceclassWhat a catalogue is asked about: a URL on any platform, an ISRC (a recording), a UPC/EAN (a release), or a platform's own id. One of them is enough; a catalogue that cannot read the kind given says so (NotSupportedException).
7 methods · 2 constants
ReleaseclassAn album, a single, an EP as the catalogues know it: its title, its artist, its label, the UPC that names it, its cover, its tracks, and the links to every platform (the label's first).
5 methods · 13 properties · 3 constants
SourceclassSomething an <audio> element can play: a file of the site's, or a catalogue's preview.
1 method · 4 properties · 2 constants
TrackclassOne recording of a release: its place, its title, who plays, the ISRC that names it everywhere, and the preview a catalogue offers (iTunes: 30 seconds, licensed for that use).
2 methods · 10 properties
EmbedOptionsclassHow an embed should look: the theme of the page it sits in, compact or full, autoplay (only after a click).
2 methods · 5 properties · 2 constants
EmbedderclassThe platforms' own players, from their public embed URLs - no key, no SDK: Spotify (open.spotify.com/embed: albums, tracks, playlists, artists), Apple Music (embed.music.apple.com), Deezer (widget.deezer.com), YouTube (youtube-nocookie.com), SoundCloud (w.soundcloud.com). Every iframe is lazy and sandboxed as the platform requires; a site loads it on a click, never with the page.
3 methods
EmbedderInterfaceinterfaceTurns a platform link into the iframe that plays it - without any key, for the platforms that allow it.
2 methods
Omnisong
Config class
final class Config extends ArrayObject Config.php:13
A catalogue'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): selfSets each key not set yet.
Config::validateNotEmpty()
public function validateNotEmpty(array $keys): voidConfig::get()
public function get(string $key, mixed $default = null): mixedPlatform enum
enum Platform Platform.php:11
Where a recording can be listened to or bought. The label comes first: a site shows "released by ES-DUR, buy it there" before "listen on Spotify". rank() orders a PlatformLinks; fromOdesli() maps song.link's keys; embeddable() says whether Player\Embedder knows an iframe for it.
case LABEL = 'label'case SHOP = 'shop'case BANDCAMP = 'bandcamp'case SPOTIFY = 'spotify'case APPLE_MUSIC = 'apple_music'case ITUNES = 'itunes'case YOUTUBE = 'youtube'case YOUTUBE_MUSIC = 'youtube_music'case DEEZER = 'deezer'case QOBUZ = 'qobuz'case IDAGIO = 'idagio'case TIDAL = 'tidal'case AMAZON_MUSIC = 'amazon_music'case AMAZON = 'amazon'case PRESTO = 'presto'case HIGHRESAUDIO = 'highresaudio'case SOUNDCLOUD = 'soundcloud'case NAPSTER = 'napster'case PANDORA = 'pandora'case ANGHAMI = 'anghami'case BOOMPLAY = 'boomplay'case AUDIOMACK = 'audiomack'case AUDIUS = 'audius'case OTHER = 'other'
Platform::rank()
public function rank(): intLower first. The label, then the shops, then the streamers by weight in classical music.
Platform::label()
public function label(): stringPlatform::embeddable()
public function embeddable(): boolWhether the core's Embedder knows an iframe for it (no key needed).
Platform::fromOdesli()
public static function fromOdesli(string $key): ?selfsong.link's platform keys (linksByPlatform) to ours; null for one we do not list.
Platform::fromUrl()
public static function fromUrl(string $url): ?selfThe platform a URL belongs to, from its host; null when unknown.
Registry class
final class Registry Registry.php:17
The catalogues by name, each built once from its factory and options:
new Registry([new OdesliCatalogFactory($http), new ItunesCatalogFactory($http)], [ 'odesli' => ['factory' => 'odesli', 'options' => ['api_key' => null]], 'itunes' => ['factory' => 'itunes', 'options' => ['country' => 'de']], ]);
Registry::__construct()
public function __construct(iterable $factories, readonly array $config)Registry::get()
public function get(string $name): CatalogInterfaceRegistry::has()
public function has(string $name): boolRegistry::names()
public function names(): arrayRegistry::all()
public function all(): array- Returns
in the configured order
Registry::factories()
public function factories(): array- Returns
the factories installed: what
factory:may name
Omnisong\Bridge\Symfony
OmnisongBundle class
final class OmnisongBundle extends AbstractBundle OmnisongBundle.php:44
Omnisong in a Symfony application: the catalogue packages installed (omnisong/odesli, omnisong/itunes) registered, the catalogues built from configuration and asked in that order by the one CatalogInterface that is autowired, the Embedder with the site's theme, and the Twig functions:
omnisong: catalogs: odesli: { factory: odesli, options: { api_key: '%env(default::ODESLI_API_KEY)%', country: 'DE' } } itunes: { factory: itunes, options: { country: 'de' } } player: theme: light country: ~
public function __construct(CatalogInterface $catalog, EmbedderInterface $embedder) }
public function __construct(CatalogInterface $itunes) } // one catalogue, by its nameAn application's own factories (a CatalogFactoryInterface) are registered too, autoconfigured.
OmnisongBundle::configure()
public function configure(DefinitionConfigurator $definition): voidOmnisongBundle::loadExtension()
public function loadExtension(array $config, ContainerConfigurator $container, ContainerBuilder $builder): voidOmnisongBundle::aggregate()
public static function aggregate(Registry $registry): CatalogEvery configured catalogue, in the configured order, as one.
Omnisong\Bridge\Twig
OmnisongExtension class
final class OmnisongExtension extends AbstractExtension OmnisongExtension.php:20
The players and the platforms' names in a template:
{{ omnisong_embed(release.links.get(platform)) }} {{ omnisong_embed('https://open.spotify.com/album/...', {theme: 'dark', compact: true}) }} {{ omnisong_platform('apple_music').label }} {{ 'apple_music'|omnisong_platform_label }}
OmnisongExtension::__construct()
public function __construct(readonly EmbedderInterface $embedder, readonly ?EmbedOptions $defaults = null)OmnisongExtension::getFunctions()
public function getFunctions(): arrayOmnisongExtension::getFilters()
public function getFilters(): arrayOmnisongExtension::embed()
public function embed(PlatformLink|string|null $linkOrUrl, array $options = []): ?stringThe iframe that plays a link, or null when its platform has none.
$optionsover the configured defaults
OmnisongExtension::platform()
public function platform(?string $value): ?PlatformOmnisongExtension::label()
public function label(Platform|string|null $value): string"apple_music" (or the Platform itself) as "Apple Music"; what is not a platform stays as it is.
Omnisong\Catalog
Catalog class
final class Catalog implements CatalogInterface Catalog.php:20
Every configured catalogue asked in turn, their answers merged: Odesli gives the links, iTunes the tracks and their previews, and the label the site knows goes first. What one catalogue cannot do the next does; a catalogue that is down is skipped, and remembered as skipped so the caller does not cache a half answer (see $incomplete).
public array $incomplete = []
Catalog::__construct()
public function __construct(iterable $catalogs)$catalogsin the order they are asked
Catalog::getName()
public function getName(): stringCatalog::names()
public function names(): arrayCatalog::links()
public function links(Reference $reference, ?Label $label = null): PlatformLinksCatalog::release()
public function release(Reference $reference, ?Label $label = null): ?ReleaseCatalog::releases()
public function releases(string $artist, int $limit = 50, ?string $country = null): arrayCatalogFactory class
abstract class CatalogFactory implements CatalogFactoryInterface CatalogFactory.php:14
The Omnibus way, at its simplest: a catalogue's factory fills a Config - its name ("omnisong.factory_name"), the options it needs ("omnisong.required_options") and their defaults - then builds the catalogue from it, on the application's HTTP client when one is given.
CatalogFactory::__construct()
public function __construct(protected readonly ?HttpClientInterface $http = null)CatalogFactory::getName()
public function getName(): stringCatalogFactory::create()
public function create(array $options = []): CatalogInterfaceCatalogFactory::createConfig()
public function createConfig(array $options = []): ConfigCatalogFactoryInterface interface
interface CatalogFactoryInterface CatalogFactoryInterface.php:6
Builds a catalogue from its options (a key, a country...).
CatalogFactoryInterface::getName()
public function getName(): stringThe name catalogues are configured with: "odesli", "itunes".
..
CatalogFactoryInterface::create()
public function create(array $options = []): CatalogInterfaceCatalogInterface interface
interface CatalogInterface CatalogInterface.php:15
A service that knows recordings: where they are (the links), what they are (a release with its tracks and previews), what an artist put out.
A catalogue answers what it can and throws NotSupportedException for the rest; the aggregator (Catalog) asks the next one.
CatalogInterface::getName()
public function getName(): stringThe name it is configured as: "odesli", "itunes".
..
CatalogInterface::links()
public function links(Reference $reference): PlatformLinksThe same recording on every platform this catalogue knows.
CatalogInterface::release()
public function release(Reference $reference): ?ReleaseThe release (its tracks, previews, cover, label...) the reference names, or null when unknown.
CatalogInterface::releases()
public function releases(string $artist, int $limit = 50, ?string $country = null): arrayWhat an artist put out, newest first.
Omnisong\Exception
InvalidConfigException class
final class InvalidConfigException extends LogicException implements OmnisongException InvalidConfigException.php:6
A catalogue misconfigured: a key missing, an unknown factory.
InvalidReferenceException class
final class InvalidReferenceException extends InvalidArgumentException implements OmnisongException InvalidReferenceException.php:6
A value Reference::parse() cannot read: neither a URL, a UPC/EAN nor an ISRC.
NotSupportedException class
final class NotSupportedException extends LogicException implements OmnisongException NotSupportedException.php:8
The catalogue does not read that kind of reference, or does not do that at all.
NotSupportedException::reference()
public static function reference(string $catalog, Reference $reference): selfNotSupportedException::operation()
public static function operation(string $catalog, string $operation): selfOmnisongException interface
interface OmnisongException extends Throwable OmnisongException.php:6
Every exception Omnisong throws.
ProviderException class
class ProviderException extends RuntimeException implements OmnisongException ProviderException.php:6
The catalogue's service answered with an error.
public readonly string $catalogpublic readonly ?int $status
ProviderException::__construct()
public function __construct(public readonly string $catalog, string $message, public readonly ?int $status = null, ?\Throwable $previous = null)RateLimitedException class
final class RateLimitedException extends UnavailableException RateLimitedException.php:6
The service asks to slow down (Odesli: 10 requests a minute without a key).
public readonly ?int $retryAfter
RateLimitedException::__construct()
public function __construct(string $catalog, public readonly ?int $retryAfter = null, ?\Throwable $previous = null)UnavailableException class
class UnavailableException extends ProviderException UnavailableException.php:9
The service could not be reached, or is down: never "not found". A caller that caches an answer must not cache this one.
Omnisong\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 = []): arrayThe 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.
$optionsthe HTTP client's options
Redaction::sensitive()
public static function sensitive(string $name): boolWhether a parameter, header or field of this name holds a credential.
Redaction::text()
public static function text(string $text, array $secrets = []): stringA 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 = []): \ThrowableA 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): \ThrowableThe failure given, the arguments out of its trace (and out of its previous ones'), as zend.exception_ignore_args would have left it.
Omnisong\Model
Artist class
final class Artist Artist.php:6
A performer as a catalogue names it, with its ids on the platforms that gave one.
public readonly string $namepublic readonly array $idsplatform value => the platform's id
public readonly ?string $urlpublic readonly ?string $imageUrl
Artist::__construct()
public function __construct(public readonly string $name, public readonly array $ids = [], public readonly ?string $url = null, public readonly ?string $imageUrl = null)$idsplatform value => the platform's id
Embed class
final class Embed Embed.php:8
An iframe that plays from a platform: its markup, its size, where it loads from (for a CSP).
public readonly Platform $platformpublic readonly string $htmlpublic readonly string $srcpublic readonly int $widthpublic readonly int $height
Embed::__construct()
public function __construct(public readonly Platform $platform, public readonly string $html, public readonly string $src, public readonly int $width, public readonly int $height)Label class
final class Label Label.php:6
The label a release came out on: who to show first, and where its shop is.
public readonly string $namepublic readonly ?string $urlpublic readonly ?string $shopUrl
Label::__construct()
public function __construct(public readonly string $name, public readonly ?string $url = null, public readonly ?string $shopUrl = null)PlatformLink class
final class PlatformLink PlatformLink.php:8
One place the recording is: the platform, the URL, the platform's own id when known.
public readonly Platform $platformpublic readonly string $urlpublic readonly ?string $idpublic readonly ?string $titleFor LABEL and SHOP: the name to show ("ES-DUR", "Presto Music")
public readonly ?string $country
PlatformLink::__construct()
public function __construct(public readonly Platform $platform, public readonly string $url, public readonly ?string $id = null, public readonly ?string $title = null, public readonly ?string $country = null)PlatformLink::title()
public function title(): stringPlatformLinks class
final class PlatformLinks implements IteratorAggregate, Countable PlatformLinks.php:14
The links of one recording, one per platform, in the order a site shows them: the label first, then the shops, then the streamers (Platform::rank()).
Immutable: merge() and with() give a new one.
PlatformLinks::__construct()
public function __construct(iterable $links = [])PlatformLinks::none()
public static function none(): selfPlatformLinks::get()
public function get(Platform $platform): ?PlatformLinkPlatformLinks::has()
public function has(Platform $platform): boolPlatformLinks::first()
public function first(): ?PlatformLinkThe first one, the label's when there is one.
PlatformLinks::with()
public function with(PlatformLink $link): selfPlatformLinks::withLabel()
public function withLabel(Label $label): selfPlatformLinks::merge()
public function merge(?self $other): selfOurs first: a platform both have keeps this one's link.
PlatformLinks::all()
public function all(): arrayPlatformLinks::embeddable()
public function embeddable(): array- Returns
those the Embedder can play
PlatformLinks::toArray()
public function toArray(): array- Returns
platform value => URL
PlatformLinks::fromArray()
public static function fromArray(array $urls, ?string $labelName = null): self$urlsplatform value => URL (unknown values become OTHER... no: skipped)
PlatformLinks::getIterator()
public function getIterator(): \TraversablePlatformLinks::count()
public function count(): intReference class
final class Reference Reference.php:13
What a catalogue is asked about: a URL on any platform, an ISRC (a recording), a UPC/EAN (a release), or a platform's own id. One of them is enough; a catalogue that cannot read the kind given says so (NotSupportedException).
const SONG = 'song'const ALBUM = 'album'
Reference::url()
public static function url(string $url, ?string $country = null): selfReference::isrc()
public static function isrc(string $isrc, ?string $country = null): selfReference::upc()
public static function upc(string $upc, ?string $country = null): selfReference::id()
public static function id(Platform $platform, string $id, string $type = self::ALBUM, ?string $country = null): selfReference::parse()
public static function parse(string $value, ?string $country = null): selfA loose string: a URL, 12-14 digits (UPC/EAN), 12 alphanumerics (ISRC).
Reference::withCountry()
public function withCountry(?string $country): selfReference::__toString()
public function __toString(): stringRelease class
final class Release Release.php:10
An album, a single, an EP as the catalogues know it: its title, its artist, its label, the UPC that names it, its cover, its tracks, and the links to every platform (the label's first).
const ALBUM = 'album'const SINGLE = 'single'const EP = 'ep'public readonly string $titlepublic readonly ?string $artistpublic readonly ?Label $labelpublic readonly ?string $upcpublic readonly ?\DateTimeImmutable $releasedAtpublic readonly ?string $coverUrlpublic readonly string $typepublic readonly array $trackspublic readonly ?PlatformLinks $linkspublic readonly ?string $genrepublic readonly ?int $trackCountpublic readonly array $idsplatform value => the platform's id
public readonly ?string $copyright
Release::__construct()
public function __construct(public readonly string $title, public readonly ?string $artist = null, public readonly ?Label $label = null, public readonly ?string $upc = null, public readonly ?\DateTimeImmutable $releasedAt = null, public readonly ?string $coverUrl = null, public readonly string $type = self::ALBUM, public readonly array $tracks = [], public readonly ?PlatformLinks $links = null, public readonly ?string $genre = null, public readonly ?int $trackCount = null, public readonly array $ids = [], public readonly ?string $copyright = null)$idsplatform value => the platform's id
Release::withLinks()
public function withLinks(PlatformLinks $links): selfRelease::withTracks()
public function withTracks(array $tracks): selfRelease::withLabel()
public function withLabel(?Label $label): selfRelease::merge()
public function merge(?self $other): selfWhat another catalogue knew that this one did not: each null filled, tracks and links merged.
Source class
final class Source Source.php:6
Something an <audio> element can play: a file of the site's, or a catalogue's preview.
const FILE = 'file'const PREVIEW = 'preview'public readonly string $urlpublic readonly string $kindpublic readonly ?string $mimepublic readonly ?int $durationseconds, when known
Source::__construct()
public function __construct(public readonly string $url, public readonly string $kind = self::FILE, public readonly ?string $mime = null, public readonly ?int $duration = null)Track class
final class Track Track.php:10
One recording of a release: its place, its title, who plays, the ISRC that names it everywhere, and the preview a catalogue offers (iTunes: 30 seconds, licensed for that use).
public readonly string $titlepublic readonly ?int $positionpublic readonly ?int $discpublic readonly ?int $durationseconds
public readonly ?string $isrcpublic readonly ?string $previewUrlpublic readonly ?string $artistpublic readonly ?string $composerpublic readonly array $idsplatform value => the platform's id
public readonly ?string $url
Track::__construct()
public function __construct(public readonly string $title, public readonly ?int $position = null, public readonly ?int $disc = null, public readonly ?int $duration = null, public readonly ?string $isrc = null, public readonly ?string $previewUrl = null, public readonly ?string $artist = null, public readonly ?string $composer = null, public readonly array $ids = [], public readonly ?string $url = null)$idsplatform value => the platform's id
Track::withPreview()
public function withPreview(?string $previewUrl): selfOmnisong\Player
EmbedOptions class
final class EmbedOptions EmbedOptions.php:6
How an embed should look: the theme of the page it sits in, compact or full, autoplay (only after a click).
const LIGHT = 'light'const DARK = 'dark'public readonly string $themepublic readonly bool $compactpublic readonly bool $autoplaypublic readonly ?string $countryISO 3166-1 alpha-2: the store Apple Music opens (its URLs carry one; this overrides)
public readonly ?string $colorA hex colour without '#', for the players that take one (SoundCloud)
EmbedOptions::__construct()
public function __construct(public readonly string $theme = self::LIGHT, public readonly bool $compact = false, public readonly bool $autoplay = false, public readonly ?string $country = null, public readonly ?string $color = null)EmbedOptions::dark()
public function dark(): boolEmbedder class
final class Embedder implements EmbedderInterface Embedder.php:16
The platforms' own players, from their public embed URLs - no key, no SDK: Spotify (open.spotify.com/embed: albums, tracks, playlists, artists), Apple Music (embed.music.apple.com), Deezer (widget.deezer.com), YouTube (youtube-nocookie.com), SoundCloud (w.soundcloud.com). Every iframe is lazy and sandboxed as the platform requires; a site loads it on a click, never with the page.
Embedder::__construct()
public function __construct(readonly ?EmbedOptions $defaults = null)$defaultshow an embed looks when embed() is not told (the site's theme)
Embedder::supports()
public function supports(Platform $platform): boolEmbedder::embed()
public function embed(PlatformLink $link, ?EmbedOptions $options = null): ?EmbedEmbedderInterface interface
interface EmbedderInterface EmbedderInterface.php:10
Turns a platform link into the iframe that plays it - without any key, for the platforms that allow it.
EmbedderInterface::supports()
public function supports(Platform $platform): boolEmbedderInterface::embed()
public function embed(PlatformLink $link, ?EmbedOptions $options = null): ?Embednull when the URL is not one this platform embeds (an artist page, a search...).