RepositoryDispatcher
in package
Reaches every method of every TwitchPHP repository from a line of chat.
This is how the bot covers the whole Helix surface without thirty hand-written
commands per repository. A call is written repository.method, and arguments
are matched to the method's parameters by name, which is what makes it
usable rather than a positional guessing game:
api channels.modify broadcaster_id=29034572 fields={"title":"Back in ten"}
api search.categories query=minecraft first=5
The repository list is read out of Twitch by reflection rather than copied,
so a repository added to TwitchPHP tomorrow is reachable here without this
file being touched. Parameter names, types and defaults come from reflection
too, which is also where api help <call> gets its signatures — there is no
second catalogue to drift out of date.
Every caller of this class is gated to Access::Owner. It can ban users, end streams and rewrite a channel; it is not a chat toy.
Tags
Table of Contents
Constants
- HIDDEN_NAMES : mixed = ['__construct', '__get', '__set', '__call', 'ge...
- Methods inherited from {@see AbstractRepository} are hidden.
Properties
- $repositories : array<string, class-string>|null
- $twitch : Twitch
Methods
- __construct() : mixed
- call() : PromiseInterface<string|int, mixed>
- Invokes `repository.method` with named arguments.
- methods() : array<int, string>
- Every callable method on one repository, sorted.
- repositories() : array<int, string>
- Every repository name, sorted.
- signature() : string
- A human-readable signature for one call, e.g.
- bind() : array<int, mixed>
- Matches supplied arguments to a method's parameters by name, coercing each into the declared type.
- canonical() : string|null
- closest() : string|null
- The nearest candidate, when one is near enough to be worth offering.
- coerce() : mixed
- Turns a chat string into the parameter's declared type.
- isHidden() : bool
- Whether a method is plumbing rather than an endpoint.
- map() : array<string, class-string>
- The repository map, read out of `Twitch` itself.
- method() : ReflectionMethod
- normalizeKey() : string
- Case- and underscore-insensitive, so `broadcasterId` and `broadcaster_id` both land.
- split() : array{0: string, 1: string}
- toArray() : array<string|int, mixed>
- JSON when it looks like JSON, otherwise a comma-separated list.
- toBool() : bool
- toInt() : int
- unknownRepository() : string
Constants
HIDDEN_NAMES
Methods inherited from {@see AbstractRepository} are hidden.
private
mixed
HIDDEN_NAMES
= ['__construct', '__get', '__set', '__call', 'getTwitch', 'jsonSerialize']
They are collection plumbing — filter(), first(), count(),
getIterator() — operating on whatever happens to be cached in memory,
which is not what someone typing api users.filter expects, and save()
and delete() take a Part that cannot be built from a line of chat. The
genuinely useful lookups all exist as named methods on the repositories
themselves (users.fetchByLogin, games.byIds), so nothing is lost.
Filtered by declaring class rather than by name, so a repository that overrides one with a real endpoint keeps it.
Properties
$repositories
private
static array<string, class-string>|null
$repositories
= null
$twitch read-only
private
Twitch
$twitch
Methods
__construct()
public
__construct(Twitch $twitch) : mixed
Parameters
- $twitch : Twitch
call()
Invokes `repository.method` with named arguments.
public
call(string $call, array<string, string> $arguments) : PromiseInterface<string|int, mixed>
Parameters
- $call : string
- $arguments : array<string, string>
Tags
Return values
PromiseInterface<string|int, mixed>methods()
Every callable method on one repository, sorted.
public
methods(string $repositoryName) : array<int, string>
Parameters
- $repositoryName : string
Tags
Return values
array<int, string>repositories()
Every repository name, sorted.
public
repositories() : array<int, string>
Return values
array<int, string>signature()
A human-readable signature for one call, e.g.
public
signature(string $call) : string
channels.modify broadcasterId=<string> fields=<array>.
Parameters
- $call : string
Tags
Return values
stringbind()
Matches supplied arguments to a method's parameters by name, coercing each into the declared type.
private
bind(ReflectionMethod $method, array<string, string> $arguments, string $canonical) : array<int, mixed>
Named-only. Positional arguments are deliberately not accepted: a
mis-ordered ban(broadcasterId, moderatorId, userId) would ban the wrong
person, silently and irreversibly, and no amount of convenience is worth
that.
Parameters
- $method : ReflectionMethod
- $arguments : array<string, string>
- $canonical : string
Return values
array<int, mixed>canonical()
private
canonical(string $name) : string|null
Parameters
- $name : string
Return values
string|nullclosest()
The nearest candidate, when one is near enough to be worth offering.
private
closest(string $needle, array<int, string> $candidates) : string|null
Parameters
- $needle : string
- $candidates : array<int, string>
Return values
string|nullcoerce()
Turns a chat string into the parameter's declared type.
private
static coerce(string $value, ReflectionParameter $parameter) : mixed
Everything arrives as text, so an int $first has to be made into one.
A wrong type here surfaces as an opaque Helix 400, so it is worth being
strict and explaining the failure in chat instead.
Parameters
- $value : string
- $parameter : ReflectionParameter
isHidden()
Whether a method is plumbing rather than an endpoint.
private
static isHidden(ReflectionMethod $method) : bool
Anything declared on the base repository is hidden — see HIDDEN_NAMES for why — but a repository that overrides one is offering a real endpoint under that name, so the check is on where the method was declared, not merely what it is called.
Parameters
- $method : ReflectionMethod
Return values
boolmap()
The repository map, read out of `Twitch` itself.
private
static map() : array<string, class-string>
Reflection rather than a copied list: the constant is private, but a duplicate here would silently stop covering repositories added later, and covering all of them is the entire point of this class.
Return values
array<string, class-string>method()
private
method(string $class, string $canonical, string $methodName) : ReflectionMethod
Parameters
- $class : string
- $canonical : string
- $methodName : string
Return values
ReflectionMethodnormalizeKey()
Case- and underscore-insensitive, so `broadcasterId` and `broadcaster_id` both land.
private
static normalizeKey(string $key) : string
Parameters
- $key : string
Return values
stringsplit()
private
split(string $call) : array{0: string, 1: string}
Parameters
- $call : string
Return values
array{0: string, 1: string}toArray()
JSON when it looks like JSON, otherwise a comma-separated list.
private
static toArray(string $value) : array<string|int, mixed>
Both are needed. ids=1,2,3 is what a list parameter wants, but
fields={"title":"x"} is what the several array $fields parameters —
channels.modify among them — actually take.
Parameters
- $value : string
Return values
array<string|int, mixed>toBool()
private
static toBool(string $value, ReflectionParameter $parameter) : bool
Parameters
- $value : string
- $parameter : ReflectionParameter
Return values
booltoInt()
private
static toInt(string $value, ReflectionParameter $parameter) : int
Parameters
- $value : string
- $parameter : ReflectionParameter
Return values
intunknownRepository()
private
unknownRepository(string $name) : string
Parameters
- $name : string