Skip to content

omnisense/omnilex API reference

Floor
Family
Version
1.x
Verified for real
Its README does not say
Licence
MIT
composer require omnisense/omnilex:1.x-dev

Read from the package's own PHP files at the commit 786b20a2d63c: 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.

Omnilex

  • Config class

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

    4 methods

  • Registry class

    The sources by name, each built once from its factory and options:

    16 methods

Omnilex\Auth

  • ClientCredentials class

    OAuth 2.0, client credentials (RFC 6749 § 4.4): the application signs in as itself, with the client id and secret its portal gave it. This is how PISTE opens the Légifrance and Judilibre APIs:

    3 methods

  • Piste class

    PISTE (piste.gouv.fr), the French State's API portal, in front of the Légifrance and Judilibre APIs: an application declared there gets a client id and a client secret, one pair for its sandbox and one for production, and signs in with the OAuth client-credentials flow.

    1 method · 3 constants

  • StaticToken class

    A token the application obtained itself.

    3 methods

  • TokenProviderInterface interface

    What signs a source's calls: a token that is valid now.

    2 methods

  • TokenStoreInterface interface

    Where a token is kept between two requests of an application, so that each does not ask the authorisation server for a new one (a PISTE token lives an hour). The Symfony bridge gives one over the application's cache.

    3 methods

Omnilex\Bridge\Symfony

  • CacheTokenStore class

    Keeps the tokens in the application's cache pool (cache.app), until they die.

    4 methods

  • OmnilexBundle class

    Omnilex in a Symfony application: the source packages installed (omnilex/legifrance, omnilex/judilibre, omnilex/eurlex, omnilex/justice-administrative) registered, the sources built from configuration and injectable by their name, as what they do:

    2 methods

Omnilex\Exception

  • AuthenticationException class

    The service refuses the credentials: a client id or secret that is wrong, an application not subscribed to the API, terms of use not accepted on the portal. Not "not found" either.

  • InvalidConfigException class

    A source misconfigured: a key missing, an unknown factory, an option a source refuses (EUR-Lex's language, Judilibre's recent). An \InvalidArgumentException, and so a \LogicException, as it was.

  • NotSupportedException class

    The source does not do that: an operation it has no interface for, an identifier it cannot read, a search criterion it cannot apply. A source refuses a criterion rather than answer unfiltered: in law, a search that silently drops its jurisdiction or its date is a wrong answer.

    3 methods

  • OmnilexException interface

    Every exception Omnilex throws.

  • ProviderException class

    The source's service answered with an error.

    1 method · 2 properties

  • RateLimitedException class

    The service asks to slow down (429), or the quota of the PISTE application is spent.

    1 method · 1 property

  • UnavailableException class

    The service could not be reached, is down, or refuses for now: never "not found". A caller that caches an answer must not cache this one, and a legal watch must not read it as "nothing new".

Omnilex\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

Omnilex\Model

  • Article class

    One article, in one version: the one in force at the date asked for.

    2 methods · 16 properties

  • Capabilities class

    What a source holds and what it can be asked. The operations are the interfaces it implements (operations() lists them); this says the rest: the kinds of documents, the identifiers it reads, the criteria its search applies.

    5 methods · 7 properties · 1 constant

  • Citation class

    A link from a document to another: the relation, read from the document asked for, and where it leads.

    1 method · 3 properties

  • Court class

    The court that gave a decision. $code is the source's own key ("cc", "CE", "TA75", "CJ"), the one Query::$jurisdictions takes for that source.

    1 method · 6 properties

  • Decision class

    A court's decision. $pseudonymised says whether the source publishes it with the names of the persons removed (Judilibre, the administrative courts' open data): Omnilex gives such a text as it is and never tries to put the names back; a site that shows it must not either. Null when the source does not say.

    2 methods · 21 properties

  • Identifier class

    One identifier of a legal document, normalised so that two spellings of it compare equal, and validated on its shape alone - no network: an identifier that parses is well formed, not known to exist.

    18 methods

  • Identifiers class

    A record's identifiers, each once, in the order they were learnt.

    14 methods

  • Kind enum

    What a source holds, and what a search asks for.

    3 cases

  • Query class

    What to ask search() and recent() for. Every criterion is optional. A source applies those it can (its Capabilities::$criteria name them) and refuses the others with a NotSupportedException rather than answer unfiltered - except $sort, a preference: a source that cannot sort that way keeps its own order.

    4 methods · 13 properties · 4 constants

  • Reference class

    A pointer to a text, an article or a decision: what a search lists and what a citation leads to. $id is the source's own identifier, the one its text(), article() or decision() reads; $identifiers hold the normalised ones (ECLI, CELEX, NOR...).

    1 method · 13 properties

  • Relation enum

    How a document relates to another: the direction is read from the document the citation was asked for.

    15 cases

  • Results class

    One page of references. $next is the cursor of the following page (pass it as Query::$cursor), null on the last one or when the source does not page.

    4 methods · 3 properties

  • Scheme enum

    The kinds of identifiers a legal document carries. Each is validated on its shape, without the network: an identifier that parses is well formed, not known to exist.

    3 methods · 14 cases

  • Status enum

    The legal state of a version of a text or of an article.

    1 method · 7 cases

  • Text class

    A text - a code, a law, a decree, a regulation, a directive - in one version: the one in force at the date asked for.

    4 methods · 17 properties

  • Token class

    An access token and when it dies.

    4 methods · 4 properties

  • Version class

    One version of a text or of an article: the dates between which it applies ($to is the last day, null when no end is known), its legal state, and the identifier that reads it again.

    3 methods · 6 properties

Omnilex\Source

  • ArticleReaderInterface interface

    A source that reads one article of a text.

    1 method

  • CitationsInterface interface

    A source that follows the links between decisions and texts.

    1 method

  • DecisionReaderInterface interface

    A source that reads a court's decision.

    1 method

  • HttpSource class

    What the sources over HTTP share: the calls, signed when the source has a token provider (a token refused once is asked afresh, once), their errors mapped the same way -

    1 method

  • RecentInterface interface

    A source that lists what is new: what a legal watch asks for.

    1 method

  • SearchInterface interface

    A source that searches its corpus.

    1 method

  • SourceFactory class

    The Omnibus way: a source's factory fills a Config - its name ("omnilex.factory_name"), the options it needs ("omnilex.required_options") and their defaults - then builds the source from it, on the application's HTTP client when one is given, and with the application's token store for the sources that sign in (PISTE).

    2 options · 4 methods

  • SourceFactoryInterface interface

    Builds a source from its options (credentials, a language, a throttle...).

    2 methods

  • SourceInterface interface

    A service that publishes sources of law: Légifrance, Judilibre, EUR-Lex, the administrative courts' open data. A source implements the capability interfaces of what its service does, and only those:

    2 methods

  • TextReaderInterface interface

    A source that reads a whole text.

    1 method

Omnilex

Config class

final class Config extends ArrayObject Config.php:13

A source'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 (a null counts as not set).

Config::validateNotEmpty()

public function validateNotEmpty(array $keys): void

Config::get()

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

Config::bool()

public function bool(string $key): bool

A boolean option: an environment variable arrives as a string, so "1", "true", "yes" and "on" are true, anything else ("false", "0", "no", empty, unset) false - where PHP's (bool) "false" is true.

Registry class

final class Registry Registry.php:30

The sources by name, each built once from its factory and options:

new Registry([new LegifranceSourceFactory($http), new EurlexSourceFactory($http)], [ 'legifrance' => ['factory' => 'legifrance', 'options' => ['client_id' => '...', 'client_secret' => '...']], 'eurlex' => ['factory' => 'eurlex', 'options' => ['language' => 'fr']], ]);

Nothing is built, nor checked, before a source is asked for: a site whose PISTE credentials are not there yet still boots.

Registry::__construct()

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

Registry::get()

public function get(string $name): SourceInterface
public function search(string $name): SearchInterface
Throws

NotSupportedException when the source does not search

Registry::texts()

public function texts(string $name): TextReaderInterface
Throws

NotSupportedException when the source does not read texts

Registry::articles()

public function articles(string $name): ArticleReaderInterface
Throws

NotSupportedException when the source does not read articles

Registry::decisions()

public function decisions(string $name): DecisionReaderInterface
Throws

NotSupportedException when the source does not read decisions

Registry::citations()

public function citations(string $name): CitationsInterface
Throws

NotSupportedException when the source does not follow links

Registry::recent()

public function recent(string $name): RecentInterface
Throws

NotSupportedException when the source does not list what is new

Registry::has()

public function has(string $name): bool

Registry::names()

public function names(): array
Returns

the configured sources, in the configured order

Registry::all()

public function all(): array
Returns

in the configured order

Registry::usable()

public function usable(): array

The sources that can be built: those whose options are complete. A source declared without its credentials yet (PISTE) is left out, where all() would refuse it.

Returns

in the configured order

Registry::having()

public function having(string $operation): array

The usable sources that do one thing: an operation ("search", "text", "article", "decision", "citations", "recent") or its interface.

Registry::reading()

public function reading(Scheme|Kind $what): array

The usable sources that read that kind of identifier, or hold that kind of document.

Registry::factories()

public function factories(): array
Returns

the factories installed: what factory: may name

Registry::options()

public function options(string $name): array

The options a source is configured with (its factory's defaults not included).

Omnilex\Auth

ClientCredentials class

final class ClientCredentials implements TokenProviderInterface ClientCredentials.php:23

OAuth 2.0, client credentials (RFC 6749 § 4.4): the application signs in as itself, with the client id and secret its portal gave it. This is how PISTE opens the Légifrance and Judilibre APIs:

POST https://oauth.piste.gouv.fr/api/oauth/token grant_type=client_credentials&client_id=...&client_secret=...&scope=openid

The token is kept until a minute before it dies, in memory and in the store when one is given.

ClientCredentials::__construct()

public function __construct(readonly HttpClientInterface $http, readonly string $tokenUri, readonly string $clientId, readonly string $clientSecret, readonly string $scope = 'openid', readonly ?TokenStoreInterface $store = null, readonly string $source = 'oauth')

ClientCredentials::token()

public function token(): Token

ClientCredentials::forget()

public function forget(): void

Piste class

final class Piste Piste.php:13

PISTE (piste.gouv.fr), the French State's API portal, in front of the Légifrance and Judilibre APIs: an application declared there gets a client id and a client secret, one pair for its sandbox and one for production, and signs in with the OAuth client-credentials flow.

const TOKEN_URI = 'https://oauth.piste.gouv.fr/api/oauth/token'
const SANDBOX_TOKEN_URI = 'https://sandbox-oauth.piste.gouv.fr/api/oauth/token'
const SCOPE = 'openid'

Piste::credentials()

public static function credentials(HttpClientInterface $http, string $clientId, string $clientSecret, bool $sandbox = false, ?TokenStoreInterface $store = null, string $source = 'piste', ?string $tokenUri = null): ClientCredentials

StaticToken class

final class StaticToken implements TokenProviderInterface StaticToken.php:8

A token the application obtained itself.

StaticToken::__construct()

public function __construct(Token|string $token)

StaticToken::token()

public function token(): Token

StaticToken::forget()

public function forget(): void

TokenProviderInterface interface

interface TokenProviderInterface TokenProviderInterface.php:10

What signs a source's calls: a token that is valid now.

TokenProviderInterface::token()

public function token(): Token
Throws

AuthenticationException when the credentials are refused

Throws

UnavailableException when the authorisation server cannot be reached

TokenProviderInterface::forget()

public function forget(): void

Drops the token in hand: the next token() asks for a fresh one (after a 401).

TokenStoreInterface interface

interface TokenStoreInterface TokenStoreInterface.php:12

Where a token is kept between two requests of an application, so that each does not ask the authorisation server for a new one (a PISTE token lives an hour). The Symfony bridge gives one over the application's cache.

TokenStoreInterface::get()

public function get(string $key): ?Token

TokenStoreInterface::set()

public function set(string $key, Token $token): void

TokenStoreInterface::delete()

public function delete(string $key): void

Omnilex\Bridge\Symfony

CacheTokenStore class

final class CacheTokenStore implements TokenStoreInterface CacheTokenStore.php:10

Keeps the tokens in the application's cache pool (cache.app), until they die.

CacheTokenStore::__construct()

public function __construct(readonly CacheItemPoolInterface $cache)

CacheTokenStore::get()

public function get(string $key): ?Token

CacheTokenStore::set()

public function set(string $key, Token $token): void

CacheTokenStore::delete()

public function delete(string $key): void

OmnilexBundle class

final class OmnilexBundle extends AbstractBundle OmnilexBundle.php:52

Omnilex in a Symfony application: the source packages installed (omnilex/legifrance, omnilex/judilibre, omnilex/eurlex, omnilex/justice-administrative) registered, the sources built from configuration and injectable by their name, as what they do:

omnilex: sources: legifrance: { factory: legifrance, options: { client_id: '%env(PISTE_CLIENT_ID)%', client_secret: '%env(PISTE_CLIENT_SECRET)%' } } judilibre: { factory: judilibre, options: { client_id: '%env(PISTE_CLIENT_ID)%', client_secret: '%env(PISTE_CLIENT_SECRET)%' } } eurlex: { factory: eurlex, options: { language: fr } } administratif: { factory: justice-administrative }

public function __construct(ArticleReaderInterface $legifrance, DecisionReaderInterface $judilibre, RecentInterface $administratif) }

Nothing is built, nor checked, when the container compiles: a source is built the first time it is asked for, and a credential left empty only shows then (InvalidConfigException). A source injected as something it does not do fails where it is injected.

The PISTE tokens are kept in cache.app, an hour each. An application's own factories (a SourceFactoryInterface) are registered too, autoconfigured.

OmnilexBundle::configure()

public function configure(DefinitionConfigurator $definition): void

OmnilexBundle::loadExtension()

public function loadExtension(array $config, ContainerConfigurator $container, ContainerBuilder $builder): void

Omnilex\Exception

AuthenticationException class

final class AuthenticationException extends UnavailableException AuthenticationException.php:10

The service refuses the credentials: a client id or secret that is wrong, an application not subscribed to the API, terms of use not accepted on the portal. Not "not found" either.

InvalidConfigException class

final class InvalidConfigException extends InvalidArgumentException implements OmnilexException InvalidConfigException.php:10

A source misconfigured: a key missing, an unknown factory, an option a source refuses (EUR-Lex's language, Judilibre's recent). An \InvalidArgumentException, and so a \LogicException, as it was.

NotSupportedException class

final class NotSupportedException extends LogicException implements OmnilexException NotSupportedException.php:11

The source does not do that: an operation it has no interface for, an identifier it cannot read, a search criterion it cannot apply. A source refuses a criterion rather than answer unfiltered: in law, a search that silently drops its jurisdiction or its date is a wrong answer.

NotSupportedException::identifier()

public static function identifier(string $source, string $identifier, string $what = 'look up'): self

NotSupportedException::operation()

public static function operation(string $source, string $operation): self

NotSupportedException::criterion()

public static function criterion(string $source, string $criterion, ?string $why = null): self

OmnilexException interface

interface OmnilexException extends Throwable OmnilexException.php:6

Every exception Omnilex throws.

ProviderException class

class ProviderException extends RuntimeException implements OmnilexException ProviderException.php:6

The source's service answered with an error.

public readonly string $source
public readonly ?int $status

ProviderException::__construct()

public function __construct(public readonly string $source, 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 (429), or the quota of the PISTE application is spent.

public readonly ?int $retryAfter

RateLimitedException::__construct()

public function __construct(string $source, public readonly ?int $retryAfter = null, ?\Throwable $previous = null)

UnavailableException class

class UnavailableException extends ProviderException UnavailableException.php:10

The service could not be reached, is down, or refuses for now: never "not found". A caller that caches an answer must not cache this one, and a legal watch must not read it as "nothing new".

Omnilex\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.

Omnilex\Model

Article class

final readonly class Article Article.php:6

One article, in one version: the one in force at the date asked for.

public string $id
public ?string $number
public string $content

Plain text.

public ?string $html
public ?string $title
public Identifiers $identifiers
public ?Version $version
public array $versions

every version the source knows of the article, oldest first

public ?string $textId
public ?string $textTitle
public ?string $path

The headings above the article: "Partie législative > Livre Ier > Titre II".

public ?string $note
public array $citations
public ?string $url
public string $source
public array $raw

Article::__construct()

public function __construct(public string $id, public ?string $number, public string $content, public ?string $html = null, public ?string $title = null, public Identifiers $identifiers = new Identifiers(), public ?Version $version = null, public array $versions = [], public ?string $textId = null, public ?string $textTitle = null, public ?string $path = null, public ?string $note = null, public array $citations = [], public ?string $url = null, public string $source = '', public array $raw = [])
$versions

every version the source knows of the article, oldest first

Article::isInForce()

public function isInForce(): bool

Capabilities class

final readonly class Capabilities Capabilities.php:19

What a source holds and what it can be asked. The operations are the interfaces it implements (operations() lists them); this says the rest: the kinds of documents, the identifiers it reads, the criteria its search applies.

const OPERATIONS = ['search' => SearchInterface::class, 'text' => TextReaderInterface::class, 'article' => ArticleReaderInterface::class, 'decision' => DecisionReaderInterface:…
public array $kinds

what the source holds

public array $identifiers

the identifiers it reads, besides its own

public array $criteria

the Query criteria its search applies (Query::CRITERIA)

public array $jurisdictions

the countries or legal orders it covers: "FR", "EU"

public bool $versions

whether it reads a text or an article as in force at a date

public ?int $pageSize

the most results it gives per page

public bool $pseudonymised

whether its decisions come with the names of the persons removed

Capabilities::__construct()

public function __construct(public array $kinds = [], public array $identifiers = [], public array $criteria = [], public array $jurisdictions = [], public bool $versions = false, public ?int $pageSize = null, public bool $pseudonymised = false)
$kinds

what the source holds

$identifiers

the identifiers it reads, besides its own

$criteria

the Query criteria its search applies (Query::CRITERIA)

$jurisdictions

the countries or legal orders it covers: "FR", "EU"

$versions

whether it reads a text or an article as in force at a date

$pageSize

the most results it gives per page

$pseudonymised

whether its decisions come with the names of the persons removed

Capabilities::holds()

public function holds(Kind $kind): bool

Capabilities::reads()

public function reads(Scheme $scheme): bool

Capabilities::filters()

public function filters(string $criterion): bool

Capabilities::operations()

public static function operations(SourceInterface $source): array

The operations a source implements: search, text, article, decision, citations, recent.

Citation class

final readonly class Citation Citation.php:6

A link from a document to another: the relation, read from the document asked for, and where it leads.

public Relation $relation
public Reference $target
public ?string $note

What the source says of the link: its own type, the provision concerned.

Citation::__construct()

public function __construct(public Relation $relation, public Reference $target, public ?string $note = null)

Court class

final readonly class Court Court.php:9

The court that gave a decision. $code is the source's own key ("cc", "CE", "TA75", "CJ"), the one Query::$jurisdictions takes for that source.

public string $name
public ?string $code
public ?string $country

"FR", "EU"

public ?string $chamber
public ?string $formation
public ?string $location

The seat, for the courts that have several: "Cour d'appel de Nancy".

Court::__construct()

public function __construct(public string $name, public ?string $code = null, public ?string $country = null, public ?string $chamber = null, public ?string $formation = null, public ?string $location = null)

Decision class

final readonly class Decision Decision.php:12

A court's decision. $pseudonymised says whether the source publishes it with the names of the persons removed (Judilibre, the administrative courts' open data): Omnilex gives such a text as it is and never tries to put the names back; a site that shows it must not either. Null when the source does not say.

public string $id
public ?string $title
public Identifiers $identifiers
public ?Court $court
public ?\DateTimeImmutable $date
public ?string $number

The main case number: pourvoi, requête, affaire.

public array $numbers

every case number, the main one first

public ?string $type

The source's own nature: "arret", "Ordonnance", "JUDG".

..

public ?string $solution
public ?string $publication

How the court published it: bulletin, recueil Lebon.

..

public ?string $summary
public array $subjects

the headings the court filed it under (titrage, themes)

public ?string $content

Plain text.

public ?string $html
public array $citations

texts applied, decisions contested or brought together

public ?bool $pseudonymised
public ?\DateTimeImmutable $updatedOn
public ?string $language

ISO 639-1.

public ?string $url
public string $source
public array $raw

Decision::__construct()

public function __construct(public string $id, public ?string $title = null, public Identifiers $identifiers = new Identifiers(), public ?Court $court = null, public ?\DateTimeImmutable $date = null, public ?string $number = null, public array $numbers = [], public ?string $type = null, public ?string $solution = null, public ?string $publication = null, public ?string $summary = null, public array $subjects = [], public ?string $content = null, public ?string $html = null, public array $citations = [], public ?bool $pseudonymised = null, public ?\DateTimeImmutable $updatedOn = null, public ?string $language = null, public ?string $url = null, public string $source = '', public array $raw = [])
$numbers

every case number, the main one first

$subjects

the headings the court filed it under (titrage, themes)

$citations

texts applied, decisions contested or brought together

Decision::ecli()

public function ecli(): ?string

Identifier class

final readonly class Identifier implements Stringable Identifier.php:17

One identifier of a legal document, normalised so that two spellings of it compare equal, and validated on its shape alone - no network: an identifier that parses is well formed, not known to exist.

Identifier::ecli('ecli:fr:ccass:2018:c301117')->value; // ECLI:FR:CCASS:2018:C301117 Identifier::celex('CELEX:32016R0679')->value; // 32016R0679 Identifier::pourvoi('n° C 17-18.194')->value; // 17-18.194 Identifier::parse('JUSC1732516D'); // nor:JUSC1732516D Identifier::parse('https://www.legifrance.gouv.fr/jorf/id/JORFTEXT000038261631'); // jorftext:JORFTEXT000038261631 Identifier::parse('https://eur-lex.europa.eu/legal-content/FR/TXT/?uri=CELEX:32016R0679'); // celex:32016R0679

Identifier::of()

public static function of(Scheme|string $scheme, string $value): self
Throws

InvalidArgumentException when the value is not a valid identifier of that scheme

Identifier::tryOf()

public static function tryOf(Scheme|string|null $scheme, ?string $value): ?self

The identifier, or null when the value is not one of that scheme.

Identifier::parse()

public static function parse(string $input): ?self

Reads an identifier from a string: "scheme:value", a page of Légifrance, EUR-Lex or the Publications Office, an ELI, or a value whose shape tells its scheme. Null when nothing is recognised.

Identifier::ecli()

public static function ecli(string $value): self

Identifier::celex()

public static function celex(string $value): self

Identifier::eli()

public static function eli(string $value): self

Identifier::nor()

public static function nor(string $value): self

Identifier::pourvoi()

public static function pourvoi(string $value): self

Identifier::legifrance()

public static function legifrance(string $value): self

One of Légifrance's identifiers, its scheme read from its prefix.

Throws

InvalidArgumentException

Identifier::key()

public function key(): string

"ecli:ECLI:FR:CCASS:2018:C301117": what collections key on.

Identifier::equals()

public function equals(self $other): bool

Identifier::country()

public function country(): ?string

An ECLI's country code ("FR", "EU"); an ELI's ("FR", "EU").

Identifier::court()

public function court(): ?string

An ECLI's court code: "CCASS", "CECHS", "C".

Identifier::year()

public function year(): ?int

The year an ECLI or a CELEX number carries.

Identifier::sector()

public function sector(): ?string

A CELEX number's sector: "3" legislation, "6" case law, "0" consolidated versions, "1" treaties.

..

Identifier::consolidatedOn()

public function consolidatedOn(): ?\DateTimeImmutable

The day a consolidated CELEX number (02016R0679-20160504) is the state of.

Identifier::url()

public function url(): ?string

The page that shows it, when the identifier alone tells which: EUR-Lex for a CELEX number and an EU ECLI, the ELI itself, Légifrance for the identifiers whose page does not depend on the kind of text. Null otherwise (a LEGITEXT is a code or a law, each with its own page: the models carry their url).

Identifier::__toString()

public function __toString(): string

Identifiers class

final readonly class Identifiers implements IteratorAggregate, Countable Identifiers.php:10

A record's identifiers, each once, in the order they were learnt.

Identifiers::__construct()

public function __construct(iterable $identifiers = [])
$identifiers

nulls (an identifier that did not parse) are skipped

Identifiers::of()

public static function of(?Identifier ...$identifiers): self

Identifiers::get()

public function get(Scheme $scheme): ?Identifier

The first identifier of that scheme.

Identifiers::value()

public function value(Scheme $scheme): ?string

The first value of that scheme: $decision->identifiers->value(Scheme::ECLI).

Identifiers::all()

public function all(?Scheme $scheme = null): array
Returns

every identifier, or those of one scheme

Identifiers::values()

public function values(Scheme $scheme): array
Returns

the values of one scheme

Identifiers::has()

public function has(Scheme|Identifier $what): bool

Identifiers::with()

public function with(?Identifier ...$identifiers): self

Identifiers::merge()

public function merge(self $other): self

Identifiers::keys()

public function keys(): array
Returns

"ecli:ECLI:FR:CCASS:2018:C301117"...

Identifiers::toArray()

public function toArray(): array
Returns

values by scheme, for storage

Identifiers::fromArray()

public static function fromArray(array $array): self
$array

what toArray() gave

Identifiers::getIterator()

public function getIterator(): \ArrayIterator

Identifiers::count()

public function count(): int

Kind enum

enum Kind Kind.php:6

What a source holds, and what a search asks for.

case TEXT = 'text'

A whole text: a code, a law, a decree, a regulation, a directive.

case ARTICLE = 'article'

One article of a text.

case DECISION = 'decision'

A court's decision.

Query class

final readonly class Query Query.php:16

What to ask search() and recent() for. Every criterion is optional. A source applies those it can (its Capabilities::$criteria name them) and refuses the others with a NotSupportedException rather than answer unfiltered - except $sort, a preference: a source that cannot sort that way keeps its own order.

new Query(text: 'responsabilité du fait des choses', kind: Kind::DECISION, jurisdictions: ['cc'], from: '2020-01-01') new Query(text: 'responsabilité', kind: Kind::ARTICLE, subjects: ['Code civil'], at: '2018-01-01') $query->with(['cursor' => $results->next])

const RELEVANCE = 'relevance'
const NEWEST = 'newest'
const OLDEST = 'oldest'
const CRITERIA = ['text', 'title', 'number', 'kind', 'jurisdictions', 'from', 'to', 'subjects', 'types', 'at']

The criteria, as Capabilities::$criteria names them.

public ?\DateTimeImmutable $from
public ?\DateTimeImmutable $to
public ?\DateTimeImmutable $at
public ?string $text

free text; in double quotes, the exact expression where the source can

public ?string $title

words of the title

public ?string $number

a number: of a text (2019-290), of an article (L36-11), of a case (17-18.194)

public ?Kind $kind
public array $jurisdictions

the source's own codes: a court, an order of courts

public array $subjects

the source's own subject headings (matière): a code's name, a theme, a subject code

public array $types

the source's own natures: LOI, DECRET, arret, REG...

public int $limit

results per page (each source caps it)

public ?string $cursor

the Results::$next of the page before

public string $sort

Query::__construct()

public function __construct(public ?string $text = null, public ?string $title = null, public ?string $number = null, public ?Kind $kind = null, public array $jurisdictions = [], \DateTimeInterface|string|null $from = null, \DateTimeInterface|string|null $to = null, public array $subjects = [], public array $types = [], \DateTimeInterface|string|null $at = null, public int $limit = 25, public ?string $cursor = null, public string $sort = self::RELEVANCE)
$text

free text; in double quotes, the exact expression where the source can

$title

words of the title

$number

a number: of a text (2019-290), of an article (L36-11), of a case (17-18.194)

$jurisdictions

the source's own codes: a court, an order of courts

$from

dated from that day (a decision's date, a text's signature)

$to

dated up to that day

$subjects

the source's own subject headings (matière): a code's name, a theme, a subject code

$types

the source's own natures: LOI, DECRET, arret, REG...

$at

texts and articles as in force on that day

$limit

results per page (each source caps it)

$cursor

the Results::$next of the page before

Query::with()

public function with(array $changes): self

Query::criteria()

public function criteria(): array

The criteria this query sets: what a source must be able to apply.

Query::day()

public static function day(\DateTimeInterface|string|null $date): ?\DateTimeImmutable

A day, at midnight UTC: dates of law have no hour.

Reference class

final readonly class Reference Reference.php:11

A pointer to a text, an article or a decision: what a search lists and what a citation leads to. $id is the source's own identifier, the one its text(), article() or decision() reads; $identifiers hold the normalised ones (ECLI, CELEX, NOR...).

public Kind $kind
public string $id
public string $title
public Identifiers $identifiers
public ?\DateTimeImmutable $date
public ?string $type

The source's own nature: "LOI", "REG", "arret".

..

public ?string $number
public ?Court $court
public ?Status $status
public ?string $summary

An excerpt or a summary, as plain text.

public ?string $url
public string $source
public array $raw

what the source answered, for what the model does not carry

Reference::__construct()

public function __construct(public Kind $kind, public string $id, public string $title, public Identifiers $identifiers = new Identifiers(), public ?\DateTimeImmutable $date = null, public ?string $type = null, public ?string $number = null, public ?Court $court = null, public ?Status $status = null, public ?string $summary = null, public ?string $url = null, public string $source = '', public array $raw = [])
$raw

what the source answered, for what the model does not carry

Relation enum

enum Relation Relation.php:6

How a document relates to another: the direction is read from the document the citation was asked for.

case CITES = 'cites'
case CITED_BY = 'cited_by'
case APPLIES = 'applies'

A decision applies a text (its visa).

case APPLIED_BY = 'applied_by'
case INTERPRETS = 'interprets'

A decision interprets a text (a preliminary ruling).

case INTERPRETED_BY = 'interpreted_by'
case AMENDS = 'amends'
case AMENDED_BY = 'amended_by'
case REPEALS = 'repeals'
case REPEALED_BY = 'repealed_by'
case BASED_ON = 'based_on'

A text adopted on the basis of another.

case BASIS_OF = 'basis_of'
case CONTESTS = 'contests'

A decision rules on another: the judgment under appeal.

case FOLLOWED_BY = 'followed_by'

The decision that came after this one in the same case.

Case law brought together by the court itself (a rapprochement).

Results class

final readonly class Results implements IteratorAggregate, Countable Results.php:12

One page of references. $next is the cursor of the following page (pass it as Query::$cursor), null on the last one or when the source does not page.

public array $items
public ?string $next
public ?int $total

how many documents the whole query matches, when the source says

Results::__construct()

public function __construct(public array $items = [], public ?string $next = null, public ?int $total = null)
$total

how many documents the whole query matches, when the source says

Results::isLast()

public function isLast(): bool

Results::getIterator()

public function getIterator(): \ArrayIterator

Results::count()

public function count(): int

Scheme enum

enum Scheme Scheme.php:10

The kinds of identifiers a legal document carries. Each is validated on its shape, without the network: an identifier that parses is well formed, not known to exist.

case ECLI = 'ecli'

European Case Law Identifier: ECLI:FR:CCASS:2018:C301117, ECLI:EU:C:2014:317.

case CELEX = 'celex'

A document of EU law in EUR-Lex: 32016R0679; a consolidated version: 02016R0679-20160504.

case ELI = 'eli'

European Legislation Identifier: http://data.europa.eu/eli/reg/2016/679/oj, /eli/decret/2018/2/13/JUSC1732516D/jo/texte.

case NOR = 'nor'

The French official number of a text published in the Journal officiel: JUSC1732516D.

case POURVOI = 'pourvoi'

An appeal number at the Cour de cassation: 17-18.194.

case LEGITEXT = 'legitext'

Légifrance: a consolidated text (a code, a law, a decree).

case LEGIARTI = 'legiarti'

Légifrance: one version of an article of a consolidated text.

case LEGISCTA = 'legiscta'

Légifrance: a section of a consolidated text.

case JORFTEXT = 'jorftext'

Légifrance: a text as published in the Journal officiel.

case JORFARTI = 'jorfarti'

Légifrance: an article as published in the Journal officiel.

case JORFCONT = 'jorfcont'

Légifrance: one issue of the Journal officiel.

case JURITEXT = 'juritext'

Légifrance: a decision of the judicial courts.

case CETATEXT = 'cetatext'

Légifrance: a decision of the administrative courts.

case CONSTEXT = 'constext'

Légifrance: a decision of the Conseil constitutionnel.

Scheme::label()

public function label(): string

Scheme::isLegifrance()

public function isLegifrance(): bool

One of Légifrance's own identifiers: a prefix and twelve digits.

Scheme::kind()

public function kind(): ?Kind

What the identifier names, when its scheme tells.

Status enum

enum Status Status.php:6

The legal state of a version of a text or of an article.

case IN_FORCE = 'in_force'
case FUTURE = 'future'

Adopted, comes into force later.

case MODIFIED = 'modified'

Replaced by a later version.

case REPEALED = 'repealed'
case ANNULLED = 'annulled'
case EXPIRED = 'expired'

No longer applicable without having been repealed (lapsed, transferred, replaced).

case UNKNOWN = 'unknown'

Status::isInForce()

public function isInForce(): bool

Text class

final readonly class Text Text.php:9

A text - a code, a law, a decree, a regulation, a directive - in one version: the one in force at the date asked for.

public string $id
public string $title
public Identifiers $identifiers
public ?string $type

The source's own nature: "CODE", "LOI", "DECRET", "REG", "DIR".

..

public ?\DateTimeImmutable $date

The date of the text: its signature, its adoption.

public ?\DateTimeImmutable $publishedOn
public ?Version $version
public array $versions

every version the source lists, oldest first (empty when it lists none)

public ?string $content

Plain text of the whole version, when the source gives it.

public ?string $html
public array $articles

in the text's order, when the source gives them apart

public array $subjects
public array $citations
public ?string $language

ISO 639-1.

public ?string $url
public string $source
public array $raw

Text::__construct()

public function __construct(public string $id, public string $title, public Identifiers $identifiers = new Identifiers(), public ?string $type = null, public ?\DateTimeImmutable $date = null, public ?\DateTimeImmutable $publishedOn = null, public ?Version $version = null, public array $versions = [], public ?string $content = null, public ?string $html = null, public array $articles = [], public array $subjects = [], public array $citations = [], public ?string $language = null, public ?string $url = null, public string $source = '', public array $raw = [])
$versions

every version the source lists, oldest first (empty when it lists none)

$articles

in the text's order, when the source gives them apart

Text::isInForce()

public function isInForce(): bool

Text::article()

public function article(string $number): ?Article

The article of that number, among those the source gave.

Text::number()

public static function number(string $number): string

"L. 36-11", "L36-11" and "l 36 11" name the same article.

Token class

final readonly class Token Token.php:6

An access token and when it dies.

public string $accessToken
public ?\DateTimeImmutable $expiresAt
public string $type
public ?string $scope

Token::__construct()

public function __construct(public string $accessToken, public ?\DateTimeImmutable $expiresAt = null, public string $type = 'Bearer', public ?string $scope = null)

Token::isExpired()

public function isExpired(int $leeway = 0, ?\DateTimeImmutable $now = null): bool

True once the token is dead, or will be within $leeway seconds.

Token::toArray()

public function toArray(): array

Token::fromArray()

public static function fromArray(array $data): self

Version class

final readonly class Version Version.php:10

One version of a text or of an article: the dates between which it applies ($to is the last day, null when no end is known), its legal state, and the identifier that reads it again.

public ?\DateTimeImmutable $from
public ?\DateTimeImmutable $to
public Status $status
public ?string $id
public ?string $label
public ?string $url

Version::__construct()

public function __construct(public ?\DateTimeImmutable $from = null, public ?\DateTimeImmutable $to = null, public Status $status = Status::UNKNOWN, public ?string $id = null, public ?string $label = null, public ?string $url = null)

Version::covers()

public function covers(\DateTimeInterface $date): bool

Whether the version applies on that day (an unknown start never does).

Version::at()

public static function at(iterable $versions, \DateTimeInterface $date): ?self

The version that applies on that day, among several.

Omnilex\Source

ArticleReaderInterface interface

interface ArticleReaderInterface extends SourceInterface ArticleReaderInterface.php:12

A source that reads one article of a text.

ArticleReaderInterface::article()

public function article(Identifier|string $id, ?string $number = null, ?\DateTimeInterface $at = null): ?Article

An article as in force on that day, or null when unknown, or not in force then. $id names the article itself (its $number is then left out) or the text it belongs to, with the article's $number.

Without a date: the version the identifier names when it names one (a Légifrance LEGIARTI), the one in force today otherwise.

Throws

NotSupportedException

Throws

UnavailableException

Throws

ProviderException

CitationsInterface interface

interface CitationsInterface extends SourceInterface CitationsInterface.php:12

A source that follows the links between decisions and texts.

CitationsInterface::citations()

public function citations(Identifier|string $id, int $limit = 100): array

The links of a document, both ways: what it cites, applies or amends, and what cites, interprets or amends it. At most $limit in each direction, in the source's order (newest first where it dates them).

Empty when the document has none, or is unknown.

Throws

NotSupportedException

Throws

UnavailableException

Throws

ProviderException

DecisionReaderInterface interface

interface DecisionReaderInterface extends SourceInterface DecisionReaderInterface.php:12

A source that reads a court's decision.

DecisionReaderInterface::decision()

public function decision(Identifier|string $id): ?Decision

The decision, or null when unknown.

Throws

NotSupportedException

Throws

UnavailableException

Throws

ProviderException

HttpSource class

abstract class HttpSource implements SourceInterface HttpSource.php:34

What the sources over HTTP share: the calls, signed when the source has a token provider (a token refused once is asked afresh, once), their errors mapped the same way -

404, 410 null 401, 403, a refused token AuthenticationException 429 RateLimitedException (Retry-After kept) 423, 5xx, transport errors UnavailableException any other 4xx ProviderException

  • a minimum interval between two calls, the reading of identifiers given as strings, and the refusal of the search criteria the source cannot apply.

HttpSource::__construct()

public function __construct(protected readonly HttpClientInterface $http, protected readonly string $baseUri, protected readonly array $headers = [], protected readonly float $throttle = 0.0, protected readonly ?TokenProviderInterface $auth = null)
$headers

sent with every call (User-Agent...)

$throttle

seconds to leave between two calls

RecentInterface interface

interface RecentInterface extends SourceInterface RecentInterface.php:12

A source that lists what is new: what a legal watch asks for.

RecentInterface::recent()

public function recent(\DateTimeInterface $since, ?Query $query = null): Results

The documents new since that day, newest first, one page at a time.

Each source says which date it reads (published, added to the base, decided). The query narrows the list (kind, jurisdictions, types...); its from, to and sort are not read.

Throws

NotSupportedException when the query sets a criterion the source cannot apply

Throws

UnavailableException never an empty page: a watch must not read "down" as "nothing new"

Throws

ProviderException

SearchInterface interface

interface SearchInterface extends SourceInterface SearchInterface.php:12

A source that searches its corpus.

public function search(Query $query): Results

The documents matching the query, one page at a time.

Throws

NotSupportedException when the query sets a criterion the source cannot apply

Throws

UnavailableException

Throws

ProviderException

SourceFactory class

abstract class SourceFactory implements SourceFactoryInterface SourceFactory.php:19

The Omnibus way: a source's factory fills a Config - its name ("omnilex.factory_name"), the options it needs ("omnilex.required_options") and their defaults - then builds the source from it, on the application's HTTP client when one is given, and with the application's token store for the sources that sign in (PISTE).

Options every source takes: base_uri, user_agent, throttle (seconds between two calls).

Options

OptionDefault
user_agentnull
throttle0.0

SourceFactory::__construct()

public function __construct(protected readonly ?HttpClientInterface $http = null, protected readonly ?TokenStoreInterface $tokens = null)

SourceFactory::getName()

public function getName(): string

SourceFactory::create()

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

SourceFactory::createConfig()

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

SourceFactoryInterface interface

interface SourceFactoryInterface SourceFactoryInterface.php:6

Builds a source from its options (credentials, a language, a throttle...).

SourceFactoryInterface::getName()

public function getName(): string

The name sources are configured with: "legifrance", "eurlex".

..

SourceFactoryInterface::create()

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

SourceInterface interface

interface SourceInterface SourceInterface.php:24

A service that publishes sources of law: Légifrance, Judilibre, EUR-Lex, the administrative courts' open data. A source implements the capability interfaces of what its service does, and only those:

SearchInterface search(Query): Results TextReaderInterface text($id, $at): ?Text ArticleReaderInterface article($id, $number, $at): ?Article DecisionReaderInterface decision($id): ?Decision CitationsInterface citations($id): list<Citation> RecentInterface recent($since, ?Query): Results

Unknown is null (or an empty page). A service that is down, refuses the credentials or asks to slow down is an UnavailableException - never read as "not found". An identifier or a criterion the source cannot take is a NotSupportedException; any other error answer a ProviderException.

SourceInterface::getName()

public function getName(): string

The name it is configured as: "legifrance", "judilibre".

..

SourceInterface::capabilities()

public function capabilities(): Capabilities

TextReaderInterface interface

interface TextReaderInterface extends SourceInterface TextReaderInterface.php:12

A source that reads a whole text.

TextReaderInterface::text()

public function text(Identifier|string $id, ?\DateTimeInterface $at = null): ?Text

The text as in force on that day (today when null), or null when the source does not know it, or knows no version of it for that day.

Throws

NotSupportedException when the source cannot read that kind of identifier

Throws

UnavailableException

Throws

ProviderException