Skip to content

omnisense/omnischolar API reference

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

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

Omnischolar

  • Collector class

    A researcher's works from every source that knows them, page after page, merged into one list:

    3 methods · 1 property

  • 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

  • Export class

    Works as a reference manager imports them: BibTeX, RIS, CSL-JSON.

    8 methods · 4 constants

  • Merger class

    The works several sources list, deduplicated: one record per work, each field taken from the source preferred for it, and the editions of a book grouped under one record.

    6 methods · 2 constants

  • Registry class

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

    7 methods

Omnischolar\Bridge\Symfony

  • OmnischolarBundle class

    Omnischolar in a Symfony application: the source packages installed (omnischolar/openalex, omnischolar/hal...) registered, the sources built from configuration and injectable by their name, the Merger with the site's preferences, the Collector and the Export:

    2 methods

Omnischolar\Exception

  • InvalidConfigException class

    A source misconfigured: a key missing, an unknown factory.

  • NotSupportedException class

    The source does not read that kind of identifier, or does not do that at all.

    2 methods

  • OmnischolarException interface

    Every exception Omnischolar 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 day's budget is spent (OpenAlex without a key).

    1 method · 1 property

  • UnavailableException class

    The service could not be reached, or is down: never "not found". A caller that caches an answer must not cache this one.

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

Omnischolar\Model

  • Affiliation class

    A line of a CV: a position held, a degree, a distinction, a membership.

    2 methods · 12 properties · 8 constants

  • Author class

    A researcher's profile, as one source knows it.

    3 methods · 12 properties

  • Contributor class

    A name on a work: an author, an editor, a translator... as the source lists it.

    5 methods · 6 properties · 3 constants

  • Identifier class

    One identifier, normalised so that two spellings of it compare equal: a DOI lower-cased and without its resolver, an ISBN as its ISBN-13, an arXiv or HAL id without its version, an ORCID with its checksum checked.

    16 methods

  • Identifiers class

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

    14 methods

  • Metrics class

    An author's counts, as one source computes them: they differ from one source to the next.

    1 method · 7 properties

  • Scheme enum

    The kinds of identifiers a scholarly record carries. An ISBN is kept as its ISBN-13 (an ISBN-10 is converted; Identifier::isbn10() gives it back).

    1 method · 13 cases

  • Venue class

    Where a work appeared: a journal, a conference, a repository, a book series.

    1 method · 7 properties · 6 constants

  • Work class

    A publication: an article, a book, a chapter, a communication, a preprint... as one source describes it, or as the Merger assembled it from several ($sources). A book whose editions were grouped carries them in $editions, newest first.

    10 methods · 27 properties

  • WorkType enum

    What a work is, in the few kinds a publication list sorts by.

    2 methods · 12 cases

Omnischolar\Source

  • Capability enum

    What a source can be asked, and what its answers hold.

    11 cases

  • HttpSource class

    What the sources over HTTP share: the calls, their errors mapped the same way (404 is null; 429 a RateLimitedException; 5xx and transport errors an UnavailableException; any other 4xx a ProviderException), a minimum interval between two calls when the service asks for one (arXiv: 3 s), and the reading of identifiers given as strings.

    5 methods

  • Page class

    One page of works. $next is the cursor of the following page (pass it as Query::$cursor), null on the last one.

    4 methods · 3 properties

  • Query class

    What to ask works() and search() for. Every criterion is optional; a source applies those it understands (its README says which) and ignores the others, except $domains, which a source without Capability::DOMAINS refuses rather than answer unfiltered.

    4 methods · 11 properties · 4 constants

  • SourceFactory class

    The Omnibus way: a source's factory fills a Config - its name ("omnischolar.factory_name"), the options it needs ("omnischolar.required_options") and their defaults - then builds the source from it, on the application's HTTP client when one is given.

    3 options · 4 methods

  • SourceFactoryInterface interface

    Builds a source from its options (a contact address, a key, a domain...).

    2 methods

  • SourceInterface interface

    A service that knows publications: OpenAlex, HAL, Crossref, ORCID, Open Library, arXiv, INSPIRE-HEP. A source answers what it can, says what that is (capabilities()), and throws NotSupportedException for the rest: an operation it does not do, an identifier it cannot read.

    6 methods

Omnischolar

Collector class

final class Collector Collector.php:22

A researcher's works from every source that knows them, page after page, merged into one list:

$works = $collector->collect(['openalex' => 'A5108007452', 'hal' => 'Keitaro Nakatani', 'crossref' => '0009-0005-1387-7295']); $collector->incomplete; // ['hal' => 'unreachable: ...'] the sources skipped: do not cache that answer

A source that is down, rate limited, or cannot read the identifier given is skipped and named in $incomplete; the others still answer.

public array $incomplete = []

Collector::__construct()

public function __construct(readonly Registry $registry, readonly Merger $merger = new Merger())

Collector::collect()

public function collect(array $profiles, ?Query $query = null, int $max = 2000): array
$profiles

the configured source's name => the author there (one or several)

$max

the most works read from one source

Returns

merged, newest first

Collector::all()

public static function all(SourceInterface $source, Identifier|string $author, ?Query $query = null, int $max = 2000): array

Every page of an author's works in one list.

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 $default = false): bool

An option read as a boolean whatever its spelling: a site's YAML or environment gives a string, and PHP's (bool) reads "false" as true.

true, 1, "1", "true", "yes", "on" are true; false, 0, "0", "false", "no", "off" and "" are false; anything else is an InvalidConfigException.

Export class

final class Export Export.php:22

Works as a reference manager imports them: BibTeX, RIS, CSL-JSON.

$export->bibtex($works); // @article{nakatani2024acid, ...} $export->ris($work); // TY - JOUR ... $export->cslJson($works); // [{"type": "article-journal", ...}] $export->format('bibtex', $works); // by name: bibtex, ris, csl-json

Citation keys are the first author's family name, the year and the title's first word ("chocron2024acid"), made unique within one export. A book whose editions the Merger grouped is cited by its newest edition.

const BIBTEX = 'bibtex'
const RIS = 'ris'
const CSL_JSON = 'csl-json'
const FORMATS = [self::BIBTEX, self::RIS, self::CSL_JSON]

Export::__construct()

public function __construct(readonly bool $abstracts = false)

Export::format()

public function format(string $format, Work|iterable $works): string

Export::contentType()

public static function contentType(string $format): string

The media type a format is served with.

Export::bibtex()

public function bibtex(Work|iterable $works): string

Export::ris()

public function ris(Work|iterable $works): string

Export::cslJson()

public function cslJson(Work|iterable $works): string

Export::csl()

public function csl(Work|iterable $works): array

CSL-JSON items, as arrays (citeproc-js, citeproc-php, pandoc read them).

Export::citationKey()

public function citationKey(Work $work): string

"chocron2024acid": the first author's family name, the year, the title's first significant word.

Merger class

final class Merger Merger.php:36

The works several sources list, deduplicated: one record per work, each field taken from the source preferred for it, and the editions of a book grouped under one record.

Two records are the same work when they share, in this order: a DOI, an ISBN (books, theses and reports only: a chapter carries its book's), an arXiv id, a HAL id; failing all, the same title in the same year. A stronger identifier that differs keeps them apart: two different DOIs are two works, whatever their titles. A preprint's title also matches the year after its own: the year it is often published. Two books with the same title and first author but no ISBN in common are two editions of one book: they are grouped, the newest first, in the group's $editions.

Preferences name, for a field, the sources in the order they are trusted; "default" orders the fields not named. A source not listed comes after those listed, in the order the lists were given:

new Merger(['default' => ['crossref', 'openalex', 'hal'], 'abstract' => ['hal', 'openalex'], 'cover' => ['openlibrary']]);

Identifiers, keywords, domains and sources are united; a work is open access when one source says so.

const DEFAULT_ORDER = ['crossref', 'openalex', 'hal', 'inspire', 'arxiv', 'orcid', 'openlibrary']
const DEFAULT_PREFERENCES = [ 'abstract' => ['hal', 'openalex', 'arxiv', 'inspire', 'crossref'], 'citations' => ['openalex', 'inspire', 'crossref'], 'cover' => ['openlibrary…

Merger::__construct()

public function __construct(array $preferences = [], readonly bool $editions = true)
$preferences

field => sources, "default" for the others

$editions

group the editions of a book

Merger::merge()

public function merge(iterable ...$lists): array
$lists

each source's works

Returns

newest first

Merger::same()

public function same(Work $a, Work $b): bool

Whether the Merger takes two records for the same work (editions aside).

Merger::newestFirst()

public static function newestFirst(array $works): array
Returns

by date, then year, newest first; undated last; stable

Merger::mainTitle()

public static function mainTitle(Work $work): string

"Planting the Seeds of Algebra, PreK-2", from a title that may carry its subtitle after a colon.

Merger::fingerprint()

public static function fingerprint(string $text): string

A title or a name as the Merger compares it: lower case, no accents, no punctuation.

Registry class

final class Registry Registry.php:17

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

new Registry([new OpenAlexSourceFactory($http), new HalSourceFactory($http)], [ 'openalex' => ['factory' => 'openalex', 'options' => ['mailto' => 'support@glitchr.io']], 'droit' => ['factory' => 'hal', 'options' => ['domains' => ['shs.droit']]], ]);

Registry::__construct()

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

Registry::get()

public function get(string $name): SourceInterface

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::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).

Omnischolar\Bridge\Symfony

OmnischolarBundle class

final class OmnischolarBundle extends AbstractBundle OmnischolarBundle.php:51

Omnischolar in a Symfony application: the source packages installed (omnischolar/openalex, omnischolar/hal...) registered, the sources built from configuration and injectable by their name, the Merger with the site's preferences, the Collector and the Export:

omnischolar: sources: openalex: { factory: openalex, options: { mailto: '%env(OMNISCHOLAR_MAILTO)%' } } hal: { factory: hal } droit: { factory: hal, options: { domains: [shs.droit] } } openlibrary: { factory: openlibrary, options: { mailto: '%env(OMNISCHOLAR_MAILTO)%' } } merger: preferences: default: [crossref, openalex, hal] abstract: [hal, openalex] editions: true export: abstracts: false

public function __construct(SourceInterface $openalex, Collector $collector, Export $export) }

An application's own factories (a SourceFactoryInterface) are registered too, autoconfigured.

OmnischolarBundle::configure()

public function configure(DefinitionConfigurator $definition): void

OmnischolarBundle::loadExtension()

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

Omnischolar\Exception

InvalidConfigException class

final class InvalidConfigException extends LogicException implements OmnischolarException InvalidConfigException.php:6

A source misconfigured: a key missing, an unknown factory.

NotSupportedException class

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

The source does not read that kind of identifier, or does not do that at all.

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

OmnischolarException interface

interface OmnischolarException extends Throwable OmnischolarException.php:6

Every exception Omnischolar throws.

ProviderException class

class ProviderException extends RuntimeException implements OmnischolarException 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 day's budget is spent (OpenAlex without a key).

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:9

The service could not be reached, or is down: never "not found". A caller that caches an answer must not cache this one.

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

Omnischolar\Model

Affiliation class

final readonly class Affiliation Affiliation.php:9

A line of a CV: a position held, a degree, a distinction, a membership.

Dates are ISO 8601, as precise as the source knows them ("2001", "1930-02").

const EMPLOYMENT = 'employment'
const EDUCATION = 'education'
const QUALIFICATION = 'qualification'
const INVITED_POSITION = 'invited-position'
const DISTINCTION = 'distinction'
const MEMBERSHIP = 'membership'
const SERVICE = 'service'
const OBSERVED = 'observed'

An institution the source saw on the author's works, without a role nor dates it can vouch for.

public string $organization
public string $kind
public ?string $role
public ?string $department
public ?string $start
public ?string $end
public ?string $city
public ?string $country
public ?string $ror
public ?string $url
public array $years

for OBSERVED: the years the institution appears on the works

public ?bool $current

Affiliation::__construct()

public function __construct(public string $organization, public string $kind = self::EMPLOYMENT, public ?string $role = null, public ?string $department = null, public ?string $start = null, public ?string $end = null, public ?string $city = null, public ?string $country = null, public ?string $ror = null, public ?string $url = null, public array $years = [], public ?bool $current = null)
$years

for OBSERVED: the years the institution appears on the works

Affiliation::isCurrent()

public function isCurrent(): bool

Current when the source says so, or when it has a start and no end.

Author class

final readonly class Author Author.php:6

A researcher's profile, as one source knows it.

public string $name
public ?string $given
public ?string $family
public Identifiers $identifiers
public array $alternativeNames

how the name is also spelt

public array $affiliations

positions, degrees, distinctions; or institutions observed on the works

public ?Metrics $metrics
public array $urls

their pages (personal site, institution, profiles)

public ?string $biography
public array $keywords

research topics

public ?string $country
public ?string $source

Author::__construct()

public function __construct(public string $name, public ?string $given = null, public ?string $family = null, public Identifiers $identifiers = new Identifiers(), public array $alternativeNames = [], public array $affiliations = [], public ?Metrics $metrics = null, public array $urls = [], public ?string $biography = null, public array $keywords = [], public ?string $country = null, public ?string $source = null)
$alternativeNames

how the name is also spelt

$affiliations

positions, degrees, distinctions; or institutions observed on the works

$urls

their pages (personal site, institution, profiles)

$keywords

research topics

Author::affiliations()

public function affiliations(string $kind): array
Returns

those of one kind (Affiliation::EMPLOYMENT...)

Author::orcid()

public function orcid(): ?string

Contributor class

final readonly class Contributor Contributor.php:6

A name on a work: an author, an editor, a translator... as the source lists it.

const AUTHOR = 'author'
const EDITOR = 'editor'
const TRANSLATOR = 'translator'
public string $name
public ?string $given
public ?string $family
public Identifiers $identifiers
public string $role
public array $affiliations

the institutions as printed on the work

Contributor::__construct()

public function __construct(public string $name, public ?string $given = null, public ?string $family = null, public Identifiers $identifiers = new Identifiers(), public string $role = self::AUTHOR, public array $affiliations = [])
$affiliations

the institutions as printed on the work

Contributor::fromName()

public static function fromName(string $name, ?Identifiers $identifiers = null, string $role = self::AUTHOR): self

"Nakatani, Keitaro" or "Keitaro Nakatani": the family name guessed from the comma, else the last word.

Contributor::familyName()

public function familyName(): string

The family name, or the last word of the name when the source gave none.

Contributor::sortName()

public function sortName(): string

"Nakatani, Keitaro", as a bibliography sorts it.

Contributor::orcid()

public function orcid(): ?string

Identifier class

final readonly class Identifier implements Stringable Identifier.php:16

One identifier, normalised so that two spellings of it compare equal: a DOI lower-cased and without its resolver, an ISBN as its ISBN-13, an arXiv or HAL id without its version, an ORCID with its checksum checked.

Identifier::doi('https://doi.org/10.1039/D4SC04973J')->value; // 10.1039/d4sc04973j Identifier::isbn('1-4129-9660-0')->value; // 9781412996600 Identifier::parse('arXiv:hep-th/9711200v3'); // arxiv:hep-th/9711200 Identifier::parse('A5108007452'); // openalex:A5108007452 (string) Identifier::orcid('0009-0005-1387-7295'); // orcid:0009-0005-1387-7295

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 resolver URL (doi.org, orcid.org, arxiv.org, hal.science, openalex.org, inspirehep.net, openlibrary.org, pubmed) or a value whose shape tells its scheme. Null when nothing is recognised: a bare number (an INSPIRE record or a PubMed id?) needs its scheme.

Identifier::doi()

public static function doi(string $value): self

Identifier::isbn()

public static function isbn(string $value): self

Identifier::arxiv()

public static function arxiv(string $value): self

Identifier::hal()

public static function hal(string $value): self

Identifier::orcid()

public static function orcid(string $value): self

Identifier::openalex()

public static function openalex(string $value): self

Identifier::inspire()

public static function inspire(string $value): self

Identifier::openlibrary()

public static function openlibrary(string $value): self

Identifier::key()

public function key(): string

"doi:10.1039/d4sc04973j": what the Merger and the collections key on.

Identifier::equals()

public function equals(self $other): bool

Identifier::url()

public function url(): ?string

The page that resolves it, when there is one.

Identifier::isbn10()

public function isbn10(): ?string

An ISBN's ISBN-10 form (only 978- ISBNs have one).

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: $work->identifiers->value(Scheme::DOI).

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

"doi:10.1039/d4sc04973j"...

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

Metrics class

final readonly class Metrics Metrics.php:6

An author's counts, as one source computes them: they differ from one source to the next.

public ?int $works
public ?int $citations
public ?int $hIndex
public ?int $i10Index
public ?float $twoYearMeanCitedness
public array $byYear

by year, oldest first

public ?string $source

Metrics::__construct()

public function __construct(public ?int $works = null, public ?int $citations = null, public ?int $hIndex = null, public ?int $i10Index = null, public ?float $twoYearMeanCitedness = null, public array $byYear = [], public ?string $source = null)
$byYear

by year, oldest first

Scheme enum

enum Scheme Scheme.php:9

The kinds of identifiers a scholarly record carries. An ISBN is kept as its ISBN-13 (an ISBN-10 is converted; Identifier::isbn10() gives it back).

case DOI = 'doi'
case ISBN = 'isbn'
case ISSN = 'issn'
case ARXIV = 'arxiv'
case HAL = 'hal'

A HAL deposit: hal-01234567, tel-..., halshs-.

..

case IDHAL = 'idhal'

A HAL author: their idHAL (keitaro-nakatani).

case ORCID = 'orcid'
case OPENALEX = 'openalex'

W... (work), A... (author), S... (source), I... (institution).

case INSPIRE = 'inspire'

An INSPIRE-HEP record number: literature or author.

case INSPIRE_BAI = 'inspire_bai'

An INSPIRE author's BAI: Juan.M.Maldacena.1

case OPENLIBRARY = 'openlibrary'

OL...W (work), OL...M (edition), OL...A (author).

case PMID = 'pmid'
case PMCID = 'pmcid'

Scheme::label()

public function label(): string

Venue class

final readonly class Venue Venue.php:6

Where a work appeared: a journal, a conference, a repository, a book series.

const JOURNAL = 'journal'
const CONFERENCE = 'conference'
const BOOK = 'book'
const BOOK_SERIES = 'book_series'
const REPOSITORY = 'repository'
const OTHER = 'other'
public string $name
public string $type
public array $issn

print and electronic, normalised (2041-6520)

public ?string $publisher
public ?string $abbreviation
public Identifiers $identifiers
public ?string $url

Venue::__construct()

public function __construct(public string $name, public string $type = self::JOURNAL, public array $issn = [], public ?string $publisher = null, public ?string $abbreviation = null, public Identifiers $identifiers = new Identifiers(), public ?string $url = null)
$issn

print and electronic, normalised (2041-6520)

Work class

final readonly class Work Work.php:14

A publication: an article, a book, a chapter, a communication, a preprint... as one source describes it, or as the Merger assembled it from several ($sources). A book whose editions were grouped carries them in $editions, newest first.

Dates are ISO 8601, as precise as the source knows them: "2024", "2024-09", "2024-09-25".

public string $title
public WorkType $type
public array $authors

in the order printed, editors included (their role says so)

public ?int $year
public ?string $date
public ?string $subtitle
public ?Venue $venue
public ?string $publisher
public ?string $volume
public ?string $issue
public ?string $pages
public ?string $edition
public ?string $abstract
public ?string $language
public ?bool $openAccess
public ?string $url
public ?string $pdfUrl
public ?string $license
public ?string $cover
public ?int $citations
public array $keywords
public array $domains

subject codes: HAL domains (shs.droit), arXiv / INSPIRE categories (hep-th)

public Identifiers $identifiers
public ?string $source
public array $sources

the sources merged into this record

public array $editions

a book's editions, newest first (Merger)

public ?string $note

Work::__construct()

public function __construct(public string $title, public WorkType $type = WorkType::OTHER, public array $authors = [], public ?int $year = null, public ?string $date = null, public ?string $subtitle = null, public ?Venue $venue = null, public ?string $publisher = null, public ?string $volume = null, public ?string $issue = null, public ?string $pages = null, public ?string $edition = null, public ?string $abstract = null, public ?string $language = null, public ?bool $openAccess = null, public ?string $url = null, public ?string $pdfUrl = null, public ?string $license = null, public ?string $cover = null, public ?int $citations = null, public array $keywords = [], public array $domains = [], public Identifiers $identifiers = new Identifiers(), public ?string $source = null, public array $sources = [], public array $editions = [], public ?string $note = null)
$authors

in the order printed, editors included (their role says so)

$domains

subject codes: HAL domains (shs.droit), arXiv / INSPIRE categories (hep-th)

$sources

the sources merged into this record

$editions

a book's editions, newest first (Merger)

Work::with()

public function with(array $changes): self

A copy with some fields changed: $work->with(['cover' => $url]).

Work::fullTitle()

public function fullTitle(): string

"Planting the Seeds of Algebra, PreK-2: Explorations for the Early Grades"

Work::id()

public function id(Scheme $scheme): ?string

Work::doi()

public function doi(): ?string

Work::isbns()

public function isbns(): array

Work::authorsOnly()

public function authorsOnly(): array
Returns

the authors only, without editors and translators

Work::editors()

public function editors(): array

Work::firstAuthor()

public function firstAuthor(): ?Contributor
public function link(): ?string

The best link to read it: the open-access PDF, else the landing page, else the DOI.

WorkType enum

enum WorkType WorkType.php:6

What a work is, in the few kinds a publication list sorts by.

case ARTICLE = 'article'

A journal article.

case BOOK = 'book'

A book, or a whole edited volume.

case CHAPTER = 'chapter'

A chapter of a book, an encyclopedia entry.

case CONFERENCE = 'conference'

A conference paper, a talk, a poster: a "communication".

case PREPRINT = 'preprint'

A preprint, a working paper.

case THESIS = 'thesis'

A doctoral thesis, a habilitation, a dissertation.

case REPORT = 'report'
case DATASET = 'dataset'
case SOFTWARE = 'software'
case REVIEW = 'review'

A book review, a peer review (a review article is an ARTICLE).

case EDITORIAL = 'editorial'

An editorial, a letter, an erratum, a cover.

case OTHER = 'other'

WorkType::label()

public function label(): string

WorkType::fromName()

public static function fromName(?string $name): self

A Crossref / CSL / OpenAlex / ORCID type name ("journal-article", "book-chapter", "proceedings-article"...).

Omnischolar\Source

Capability enum

enum Capability Capability.php:6

What a source can be asked, and what its answers hold.

case AUTHOR = 'author'

author(): a profile.

case WORKS = 'works'

works(): an author's works, page by page.

case WORK = 'work'

work(): one work by an identifier.

search(): works by text, title, author, year, type.

case METRICS = 'metrics'

An author's counts: works, citations, h-index.

case CITATIONS = 'citations'

Each work's citation count.

case ABSTRACTS = 'abstracts'
case OPEN_ACCESS = 'open_access'

Open-access status and full-text links.

case COVERS = 'covers'

Book covers.

case AFFILIATIONS = 'affiliations'

A CV: positions, degrees, distinctions.

case DOMAINS = 'domains'

Filtering by subject domain (Query::$domains).

HttpSource class

abstract class HttpSource implements SourceInterface HttpSource.php:23

What the sources over HTTP share: the calls, their errors mapped the same way (404 is null; 429 a RateLimitedException; 5xx and transport errors an UnavailableException; any other 4xx a ProviderException), a minimum interval between two calls when the service asks for one (arXiv: 3 s), and the reading of identifiers given as strings.

HttpSource::__construct()

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

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

$throttle

seconds to leave between two calls

HttpSource::author()

public function author(Identifier|string $author): ?\Omnischolar\Model\Author

HttpSource::works()

public function works(Identifier|string $author, ?Query $query = null): Page

HttpSource::work()

public function work(Identifier|string $id): ?\Omnischolar\Model\Work
public function search(Query $query): Page

Page class

final readonly class Page implements IteratorAggregate, Countable Page.php:13

One page of works. $next is the cursor of the following page (pass it as Query::$cursor), null on the last one.

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

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

Page::__construct()

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

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

Page::isLast()

public function isLast(): bool

Page::getIterator()

public function getIterator(): \ArrayIterator

Page::count()

public function count(): int

Query class

final readonly class Query Query.php:16

What to ask works() and search() for. Every criterion is optional; a source applies those it understands (its README says which) and ignores the others, except $domains, which a source without Capability::DOMAINS refuses rather than answer unfiltered.

new Query(text: 'responsabilité civile', domains: ['shs.droit'], from: 2020, limit: 50) $query->with(['cursor' => $page->next])

const NEWEST = 'newest'
const OLDEST = 'oldest'
const RELEVANCE = 'relevance'
const CITED = 'cited'
public ?string $text
public ?string $title
public ?string $author
public ?int $from
public ?int $to
public array $types

only these kinds of works

public array $domains

subject codes: a HAL domain (shs.droit), an arXiv or INSPIRE category (hep-th)

public ?bool $openAccess
public int $limit

works per page (each source caps it)

public ?string $cursor

the Page::$next of the page before

public string $sort

Query::__construct()

public function __construct(public ?string $text = null, public ?string $title = null, public ?string $author = null, public ?int $from = null, public ?int $to = null, public array $types = [], public array $domains = [], public ?bool $openAccess = null, public int $limit = 25, public ?string $cursor = null, public string $sort = self::NEWEST)
$types

only these kinds of works

$domains

subject codes: a HAL domain (shs.droit), an arXiv or INSPIRE category (hep-th)

$limit

works per page (each source caps it)

$cursor

the Page::$next of the page before

Query::with()

public function with(array $changes): self

Query::hasYears()

public function hasYears(): bool

The year range, as one inclusive pair (either end may be open).

Query::inYears()

public function inYears(?int $year): bool

Whether a year falls within the range (an unknown year does when there is no range).

SourceFactory class

abstract class SourceFactory implements SourceFactoryInterface SourceFactory.php:17

The Omnibus way: a source's factory fills a Config - its name ("omnischolar.factory_name"), the options it needs ("omnischolar.required_options") and their defaults - then builds the source from it, on the application's HTTP client when one is given.

Options every source takes: base_uri, mailto (the contact address the polite APIs ask for), user_agent, throttle (seconds between two calls).

Options

OptionDefault
mailtonull
user_agentnull
throttle0.0

SourceFactory::__construct()

public function __construct(protected readonly ?HttpClientInterface $http = 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 (a contact address, a key, a domain...).

SourceFactoryInterface::getName()

public function getName(): string

The name sources are configured with: "openalex", "hal".

..

SourceFactoryInterface::create()

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

SourceInterface interface

interface SourceInterface SourceInterface.php:30

A service that knows publications: OpenAlex, HAL, Crossref, ORCID, Open Library, arXiv, INSPIRE-HEP. A source answers what it can, says what that is (capabilities()), and throws NotSupportedException for the rest: an operation it does not do, an identifier it cannot read.

An author or a work is named by an Identifier, or by a string the source reads: one of its own identifiers ("A5108007452", "OL7092953A"), or for the sources that search by name, a name ("Monica Neagoy").

Unknown is null (or an empty page); a service that is down or refuses is an UnavailableException (RateLimitedException when asked to slow down); any other error answer a ProviderException.

SourceInterface::getName()

public function getName(): string

The name it is configured as: "openalex", "hal".

..

SourceInterface::capabilities()

public function capabilities(): array

SourceInterface::author()

public function author(Identifier|string $author): ?Author

The researcher's profile, or null when unknown.

SourceInterface::works()

public function works(Identifier|string $author, ?Query $query = null): Page

An author's works, one page at a time: newest first unless the query sorts otherwise.

SourceInterface::work()

public function work(Identifier|string $id): ?Work

One work, or null when unknown.

public function search(Query $query): Page

Works matching the query, one page at a time.