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.
ClientCredentialsclassOAuth 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
PisteclassPISTE (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
StaticTokenclassA token the application obtained itself.
3 methods
TokenProviderInterfaceinterfaceWhat signs a source's calls: a token that is valid now.
2 methods
TokenStoreInterfaceinterfaceWhere 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
CacheTokenStoreclassKeeps the tokens in the application's cache pool (cache.app), until they die.
4 methods
OmnilexBundleclassOmnilex 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
AuthenticationExceptionclassThe 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.
InvalidConfigExceptionclassA 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.
NotSupportedExceptionclassThe 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
OmnilexExceptioninterfaceEvery exception Omnilex throws.
ProviderExceptionclassThe source's service answered with an error.
1 method · 2 properties
RateLimitedExceptionclassThe service asks to slow down (429), or the quota of the PISTE application is spent.
1 method · 1 property
UnavailableExceptionclassThe 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".
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
ArticleclassOne article, in one version: the one in force at the date asked for.
2 methods · 16 properties
CapabilitiesclassWhat 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
CitationclassA link from a document to another: the relation, read from the document asked for, and where it leads.
1 method · 3 properties
CourtclassThe 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
DecisionclassA 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
IdentifierclassOne 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
IdentifiersclassA record's identifiers, each once, in the order they were learnt.
14 methods
KindenumWhat a source holds, and what a search asks for.
3 cases
QueryclassWhat 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
ReferenceclassA 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
RelationenumHow a document relates to another: the direction is read from the document the citation was asked for.
15 cases
ResultsclassOne 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
SchemeenumThe 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
StatusenumThe legal state of a version of a text or of an article.
1 method · 7 cases
TextclassA 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
TokenclassAn access token and when it dies.
4 methods · 4 properties
VersionclassOne 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
ArticleReaderInterfaceinterfaceA source that reads one article of a text.
1 method
CitationsInterfaceinterfaceA source that follows the links between decisions and texts.
1 method
DecisionReaderInterfaceinterfaceA source that reads a court's decision.
1 method
HttpSourceclassWhat 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
RecentInterfaceinterfaceA source that lists what is new: what a legal watch asks for.
1 method
SearchInterfaceinterfaceA source that searches its corpus.
1 method
SourceFactoryclassThe 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
SourceFactoryInterfaceinterfaceBuilds a source from its options (credentials, a language, a throttle...).
2 methods
SourceInterfaceinterfaceA 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
TextReaderInterfaceinterfaceA 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): selfSets each key not set yet (a null counts as not set).
Config::validateNotEmpty()
public function validateNotEmpty(array $keys): voidConfig::get()
public function get(string $key, mixed $default = null): mixedConfig::bool()
public function bool(string $key): boolA 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): SourceInterfaceRegistry::search()
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): boolRegistry::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(): arrayThe 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): arrayThe 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): arrayThe 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): arrayThe 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(): TokenClientCredentials::forget()
public function forget(): voidPiste 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): ClientCredentialsStaticToken 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(): TokenStaticToken::forget()
public function forget(): voidTokenProviderInterface 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(): voidDrops 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): ?TokenTokenStoreInterface::set()
public function set(string $key, Token $token): voidTokenStoreInterface::delete()
public function delete(string $key): voidOmnilex\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): ?TokenCacheTokenStore::set()
public function set(string $key, Token $token): voidCacheTokenStore::delete()
public function delete(string $key): voidOmnilexBundle 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): voidOmnilexBundle::loadExtension()
public function loadExtension(array $config, ContainerConfigurator $container, ContainerBuilder $builder): voidOmnilex\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'): selfNotSupportedException::operation()
public static function operation(string $source, string $operation): selfNotSupportedException::criterion()
public static function criterion(string $source, string $criterion, ?string $why = null): selfOmnilexException 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 $sourcepublic 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 = []): 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.
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 $idpublic ?string $numberpublic string $contentPlain text.
public ?string $htmlpublic ?string $titlepublic Identifiers $identifierspublic ?Version $versionpublic array $versionsevery version the source knows of the article, oldest first
public ?string $textIdpublic ?string $textTitlepublic ?string $pathThe headings above the article: "Partie législative > Livre Ier > Titre II".
public ?string $notepublic array $citationspublic ?string $urlpublic string $sourcepublic 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 = [])$versionsevery version the source knows of the article, oldest first
Article::isInForce()
public function isInForce(): boolCapabilities 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 $kindswhat the source holds
public array $identifiersthe identifiers it reads, besides its own
public array $criteriathe Query criteria its search applies (Query::CRITERIA)
public array $jurisdictionsthe countries or legal orders it covers: "FR", "EU"
public bool $versionswhether it reads a text or an article as in force at a date
public ?int $pageSizethe most results it gives per page
public bool $pseudonymisedwhether 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)$kindswhat the source holds
$identifiersthe identifiers it reads, besides its own
$criteriathe Query criteria its search applies (Query::CRITERIA)
$jurisdictionsthe countries or legal orders it covers: "FR", "EU"
$versionswhether it reads a text or an article as in force at a date
$pageSizethe most results it gives per page
$pseudonymisedwhether its decisions come with the names of the persons removed
Capabilities::holds()
public function holds(Kind $kind): boolCapabilities::reads()
public function reads(Scheme $scheme): boolCapabilities::filters()
public function filters(string $criterion): boolCapabilities::operations()
public static function operations(SourceInterface $source): arrayThe 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 $relationpublic Reference $targetpublic ?string $noteWhat 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 $namepublic ?string $codepublic ?string $country"FR", "EU"
public ?string $chamberpublic ?string $formationpublic ?string $locationThe 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 $idpublic ?string $titlepublic Identifiers $identifierspublic ?Court $courtpublic ?\DateTimeImmutable $datepublic ?string $numberThe main case number: pourvoi, requête, affaire.
public array $numbersevery case number, the main one first
public ?string $typeThe source's own nature: "arret", "Ordonnance", "JUDG".
..
public ?string $solutionpublic ?string $publicationHow the court published it: bulletin, recueil Lebon.
..
public ?string $summarypublic array $subjectsthe headings the court filed it under (titrage, themes)
public ?string $contentPlain text.
public ?string $htmlpublic array $citationstexts applied, decisions contested or brought together
public ?bool $pseudonymisedpublic ?\DateTimeImmutable $updatedOnpublic ?string $languageISO 639-1.
public ?string $urlpublic string $sourcepublic 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 = [])$numbersevery case number, the main one first
$subjectsthe headings the court filed it under (titrage, themes)
$citationstexts applied, decisions contested or brought together
Decision::ecli()
public function ecli(): ?stringIdentifier 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): ?selfThe identifier, or null when the value is not one of that scheme.
Identifier::parse()
public static function parse(string $input): ?selfReads 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): selfIdentifier::celex()
public static function celex(string $value): selfIdentifier::eli()
public static function eli(string $value): selfIdentifier::nor()
public static function nor(string $value): selfIdentifier::pourvoi()
public static function pourvoi(string $value): selfIdentifier::legifrance()
public static function legifrance(string $value): selfOne 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): boolIdentifier::country()
public function country(): ?stringAn ECLI's country code ("FR", "EU"); an ELI's ("FR", "EU").
Identifier::court()
public function court(): ?stringAn ECLI's court code: "CCASS", "CECHS", "C".
Identifier::year()
public function year(): ?intThe year an ECLI or a CELEX number carries.
Identifier::sector()
public function sector(): ?stringA CELEX number's sector: "3" legislation, "6" case law, "0" consolidated versions, "1" treaties.
..
Identifier::consolidatedOn()
public function consolidatedOn(): ?\DateTimeImmutableThe day a consolidated CELEX number (02016R0679-20160504) is the state of.
Identifier::url()
public function url(): ?stringThe 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(): stringIdentifiers 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 = [])$identifiersnulls (an identifier that did not parse) are skipped
Identifiers::of()
public static function of(?Identifier ...$identifiers): selfIdentifiers::get()
public function get(Scheme $scheme): ?IdentifierThe first identifier of that scheme.
Identifiers::value()
public function value(Scheme $scheme): ?stringThe 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): boolIdentifiers::with()
public function with(?Identifier ...$identifiers): selfIdentifiers::merge()
public function merge(self $other): selfIdentifiers::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$arraywhat toArray() gave
Identifiers::getIterator()
public function getIterator(): \ArrayIteratorIdentifiers::count()
public function count(): intKind 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 $frompublic ?\DateTimeImmutable $topublic ?\DateTimeImmutable $atpublic ?string $textfree text; in double quotes, the exact expression where the source can
public ?string $titlewords of the title
public ?string $numbera number: of a text (2019-290), of an article (L36-11), of a case (17-18.194)
public ?Kind $kindpublic array $jurisdictionsthe source's own codes: a court, an order of courts
public array $subjectsthe source's own subject headings (matière): a code's name, a theme, a subject code
public array $typesthe source's own natures: LOI, DECRET, arret, REG...
public int $limitresults per page (each source caps it)
public ?string $cursorthe 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)$textfree text; in double quotes, the exact expression where the source can
$titlewords of the title
$numbera number: of a text (2019-290), of an article (L36-11), of a case (17-18.194)
$jurisdictionsthe source's own codes: a court, an order of courts
$fromdated from that day (a decision's date, a text's signature)
$todated up to that day
$subjectsthe source's own subject headings (matière): a code's name, a theme, a subject code
$typesthe source's own natures: LOI, DECRET, arret, REG...
$attexts and articles as in force on that day
$limitresults per page (each source caps it)
$cursorthe Results::$next of the page before
Query::with()
public function with(array $changes): selfQuery::criteria()
public function criteria(): arrayThe criteria this query sets: what a source must be able to apply.
Query::day()
public static function day(\DateTimeInterface|string|null $date): ?\DateTimeImmutableA 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 $kindpublic string $idpublic string $titlepublic Identifiers $identifierspublic ?\DateTimeImmutable $datepublic ?string $typeThe source's own nature: "LOI", "REG", "arret".
..
public ?string $numberpublic ?Court $courtpublic ?Status $statuspublic ?string $summaryAn excerpt or a summary, as plain text.
public ?string $urlpublic string $sourcepublic array $rawwhat 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 = [])$rawwhat 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 $itemspublic ?string $nextpublic ?int $totalhow 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)$totalhow many documents the whole query matches, when the source says
Results::isLast()
public function isLast(): boolResults::getIterator()
public function getIterator(): \ArrayIteratorResults::count()
public function count(): intScheme 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(): stringScheme::isLegifrance()
public function isLegifrance(): boolOne of Légifrance's own identifiers: a prefix and twelve digits.
Scheme::kind()
public function kind(): ?KindWhat 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(): boolText 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 $idpublic string $titlepublic Identifiers $identifierspublic ?string $typeThe source's own nature: "CODE", "LOI", "DECRET", "REG", "DIR".
..
public ?\DateTimeImmutable $dateThe date of the text: its signature, its adoption.
public ?\DateTimeImmutable $publishedOnpublic ?Version $versionpublic array $versionsevery version the source lists, oldest first (empty when it lists none)
public ?string $contentPlain text of the whole version, when the source gives it.
public ?string $htmlpublic array $articlesin the text's order, when the source gives them apart
public array $subjectspublic array $citationspublic ?string $languageISO 639-1.
public ?string $urlpublic string $sourcepublic 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 = [])$versionsevery version the source lists, oldest first (empty when it lists none)
$articlesin the text's order, when the source gives them apart
Text::isInForce()
public function isInForce(): boolText::article()
public function article(string $number): ?ArticleThe 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 $accessTokenpublic ?\DateTimeImmutable $expiresAtpublic string $typepublic ?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): boolTrue once the token is dead, or will be within $leeway seconds.
Token::toArray()
public function toArray(): arrayToken::fromArray()
public static function fromArray(array $data): selfVersion 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 $frompublic ?\DateTimeImmutable $topublic Status $statuspublic ?string $idpublic ?string $labelpublic ?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): boolWhether the version applies on that day (an unknown start never does).
Version::at()
public static function at(iterable $versions, \DateTimeInterface $date): ?selfThe 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): ?ArticleAn 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): arrayThe 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): ?DecisionThe 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)$headerssent with every call (User-Agent...)
$throttleseconds 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): ResultsThe 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.
SearchInterface::search()
public function search(Query $query): ResultsThe 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
| Option | Default | |
|---|---|---|
user_agent | null | |
throttle | 0.0 |
SourceFactory::__construct()
public function __construct(protected readonly ?HttpClientInterface $http = null, protected readonly ?TokenStoreInterface $tokens = null)SourceFactory::getName()
public function getName(): stringSourceFactory::create()
public function create(array $options = []): SourceInterfaceSourceFactory::createConfig()
public function createConfig(array $options = []): ConfigSourceFactoryInterface interface
interface SourceFactoryInterface SourceFactoryInterface.php:6
Builds a source from its options (credentials, a language, a throttle...).
SourceFactoryInterface::getName()
public function getName(): stringThe name sources are configured with: "legifrance", "eurlex".
..
SourceFactoryInterface::create()
public function create(array $options = []): SourceInterfaceSourceInterface 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(): stringThe name it is configured as: "legifrance", "judilibre".
..
SourceInterface::capabilities()
public function capabilities(): CapabilitiesTextReaderInterface 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): ?TextThe 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