---
sidebar_position: 10
---

# PHP reference

Everything is on `wordplus_realtime()`, the newest copy of the package on the site. Call it from `plugins_loaded` on.

## Channels

| Method | Returns | |
|---|---|---|
| `channel( $prefix, $authorize )` | `$this` | owns the channels whose names start with `$prefix`. `$authorize( $user_id, $channel )` answers `false`, `true`, or `array( 'info' => …, 'id' => … )` ([channels](channels.md), [presence](presence.md)) |
| `publish( $channels, $event, $data = null, $args = array() )` | `true` or `WP_Error` | an event to up to 100 channels; `$args`: `except`, `seal`, `blocking`, `timeout` ([publishing](publishing.md)) |
| `publish_batch( $events, $args = array() )` | `true` or `WP_Error` | up to 10 events, each `channels`, `event`, `data`, `except`, `seal` |
| `channel_info( $channel )` | array or `WP_Error` | `subscriptions`, and a presence channel's `members` |
| `token( $channels, $user = null, $info = null, $ttl = null )` | string or `null` | a channels token you hand out yourself, in place of the auth route |
| `authorize( $channels, $user_id )` | array | what the auth route answers: `token`, `exp`, `keys`, `denied` |
| `may_join( $channel, $user_id )` | bool | whether the channel's owner lets the user in, as the auth route asks it |
| `script()` | handle | the page script with its settings in `window.wordplusRealtimeConfig`; an empty handle on a site without credentials |

## Calls

| Method | Returns | |
|---|---|---|
| `calls( $prefix, $authorize )` | `$this` | owns the calls and rooms whose names start with `$prefix`. `$authorize( $user_id, $call, $with )` answers `false`, `true`, or `array( 'info' => …, 'publish' => …, 'subscribe' => …, 'admin' => …, 'hidden' => … )`; `$with` is the other person, or `null` for a room ([calls](calls.md), [group calls](group-calls.md)) |
| `calls_script()` | handle | the calls script, `window.wordplusRealtimeCalls`, after the page script; the empty handle without credentials |
| `call_screen( $args = array() )` | bool | loads [the call screen](call-screen.md) on the page; `$args['ring']` false: nothing rings on it |
| `call_user()` | int | who takes part in calls on this page: `user()` |
| `authorize_call( $request, $user_id )` | array | what the calls route answers: `token`, `exp`, `key` for a call, or `denied` |
| `screen_strings()` | array | the call screen's words in the site's language |
| `WordPlus_Realtime::call_key( $id, $caller, $callee )` | string | the key a call's two pages seal their negotiation with |

## Keys and the site's users

[Encryption](encryption.md) explains them. On `wordplus_realtime()->keys()`:

| Method | Returns | |
|---|---|---|
| `seal( $value, $label )`, `seal_json( $data, $label )` | string or `null` | a value sealed with a label's key: only those who may have that key open it |
| `open( $value )` | string or `null` | what a value this site sealed holds; `null` for anything else or anything changed |
| `WordPlus_Realtime_Keys::label_of( $value )` | string or `null` | the label of the key that opens a sealed value |
| `day_label()`, `user_label( $user_id )`, `channel_label( $channel )` | string | the day's key, a user's own, a private or presence channel's newest |
| `rotate_user( $user_id )`, `rotate_channel( $channel )` | | the next key, which someone who lost access never gets |
| `kind( $kind, $may_have, $newest = null )` | `$this` | keys of your own, `{kind}:{…}`: `$may_have( $rest, $user_id, $label )` says who may have one; `$newest( $rest, $label )` names the newest of the same thing |
| `may_have( $label, $user_id )` | bool | whether the user may have a key |
| `entry( $label )` | string | a key as the site hands it to a browser |
| `user_entries( $user_id )` | string[] | the keys a user starts with: their own, and the day's from yesterday's to tomorrow's |
| `profile( $user_id )` | array or `null` | the user's entry in the site's directory, sealed (`pd`, `pdh`) |
| `sealing()` | bool | whether the site seals (`wordplus_realtime_seal`) |

And on `wordplus_realtime()`:

| Method | Returns | |
|---|---|---|
| `user()` | int | who the site knows on this request: the signed-in user, a visitor's negative id (`wordplus_realtime_visitor_id`), or 0 |
| `identity( $user_id )` | `array( 'token', 'exp' )` or `null` | who the user is for the realtime server, with their directory entry, signed as the site |

## The site

| Method | Returns | |
|---|---|---|
| `available()` | bool | the site has its credentials |
| `credentials()` | `array( 'key', 'secret' )` or `null` | the site key and the secret to sign with now |
| `site_key()` | string | the site key, or `''` |
| `connect()->url( $return_to )` | URL | WordPlus Cloud's approval, back to `$return_to` with `wordplus_realtime=connected`, `denied` or `failed` |
| `server()`, `api_server()` | URL | where browsers connect, and where the site's requests go |
| `config()` | array | what the page gets in `window.wordplusRealtimeConfig` |
| `version()` | string | this copy's version |

## Routes

| Route | |
|---|---|
| `POST /wp-json/wordplus/v1/realtime/auth` | `{ channels }` → `{ token, exp, denied }` |
| `POST /wp-json/wordplus/v1/realtime/calls` | `{ line: true }`, `{ call, id, role, to or from, type }` or `{ room, type }` → `{ token, exp, key? }` or `{ denied }` |
| `POST /wp-json/wordplus/v1/realtime/keys` | `{ labels }` → `{ keys }`, those the user may have; `{ labels: [] }` → the keys they start with and their `identity` |

Anyone may ask; your callbacks decide. A refusal is an answer, not an HTTP error.

## Filters

| Filter | Default | |
|---|---|---|
| `wordplus_realtime_token_ttl` | 21600 | a channels token's life in seconds, at most a day |
| `wordplus_realtime_call_token_ttl` | 21600 | a calls token's, at most 6 hours |
| `wordplus_realtime_visitor_id` | 0 | a visitor's id, a negative number: who takes part in calls and gets keys |
| `wordplus_realtime_seal` | true | whether what the site sends through WordPlus Cloud goes sealed |
| `wordplus_realtime_user_has_keys` | true | `false` keeps every key from a user you cut off (`$has, $user_id`) |
| `wordplus_realtime_profile` | name, avatar, author page | a user's entry in the site's directory (`$profile, $user_id`); text is sealed |
| `wordplus_realtime_call_screen_strings` | the words | the call screen's words |
| `wordplus_realtime_server` | `https://ws.wordplus.cloud/` | where browsers connect |
| `wordplus_realtime_api_server` | `https://rest.wordplus.cloud/` | where the site's requests and a closing page's leave go |
| `wordplus_realtime_account` | `https://www.wordplus.cloud/` | where Connect sends the administrator |
| `wordplus_realtime_account_api` | `https://api.wordplus.cloud/` | where Connect's code is exchanged |

## The option

The credentials live in `wordplus_cloud_license`, which every WordPlus plugin on the site shares: on a network, the network's when the site has none. The package only reads it, but Connect writes it.

The master key every other key is derived from lives in `wordplus_realtime_master_key`, the network's on a network. It never leaves the site; deleting it changes every key, and what was sealed before no longer opens.
