diff --git a/README.md b/README.md index 6529cda9..a6c6957f 100644 --- a/README.md +++ b/README.md @@ -54,40 +54,61 @@ The fourth parameter is an `$options` array. The additional options are: * `scheme` - e.g. http or https * `host` - the host e.g. api.pusherapp.com. No trailing forward slash * `port` - the http port -* `path` - a prefix to append to all request paths. This is only useful if you are running the library against an endpoint you control yourself (e.g. a proxy that routes based on the path prefix). +* `path` - a prefix to append to all request paths. This is only useful if you + are running the library against an endpoint you control yourself (e.g. a + proxy that routes based on the path prefix). * `timeout` - the HTTP timeout * `useTLS` - quick option to use scheme of https and port 443. * `cluster` - specify the cluster where the application is running from. * `curl_options` - array with custom curl commands -* `encryption_master_key` - a 32 char long key. This key, along with the channel name, are used to derive per-channel encryption keys. Per-channel keys are used encrypt event data on encrypted channels. -* `debug` - (default `false`) if `true`, every `trigger()` and `triggerBatch()` call will return a `$response` object (e.g.): ```Array ([body] => {} [status] => 200)``` +* `encryption_master_key` - a 32 char long key. This key, along with the + channel name, are used to derive per-channel encryption keys. Per-channel + keys are used encrypt event data on encrypted channels. +* `debug` - (default `false`) if `true`, every `trigger()` and `triggerBatch()` + call will return a `$response` object (e.g.): `Array ([body] => {} [status] + => 200)` -For example, by default calls will be made over a non-TLS connection. To change this to make calls over HTTPS use: +For example, by default calls will be made over a non-TLS connection. To change +this to make calls over HTTPS use: ```php $pusher = new Pusher\Pusher( $app_key, $app_secret, $app_id, array( 'cluster' => $app_cluster, 'useTLS' => true ) ); ``` For example, if you want to set custom curl options, use this: + ```php -$pusher = new Pusher\Pusher( $app_key, $app_secret, $app_id, array( 'cluster' => $app_cluster, 'useTLS' => true, 'curl_options' => array( CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4 ) ) ); +$pusher = new Pusher\Pusher( + $app_key, + $app_secret, + $app_id, + array( + 'cluster' => $app_cluster, + 'useTLS' => true, + 'curl_options' => array( CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4 ) + ) +); ``` +**Note**: The `host` option overrides the `cluster` option! -*Note: The `$options` parameter was introduced in version 2.2.0 of the library. -Previously additional parameters could be passed for each option, but this was -becoming unwieldy. However, backwards compatibility has been maintained.* - -*Note: The `host` option overrides the `cluster` option!* +**Note:** The `$options` parameter was introduced in version 2.2.0 of the +library. Previously additional parameters could be passed for each option, but +this was becoming unwieldy. However, backwards compatibility has been +maintained. ## Logging configuration -It is strongly recommended that you configure a logger. -By default errors are easy to miss because the library will only return `false` if anything fails. +It is strongly recommended that you configure a logger. By default errors are +easy to miss because the library will only return `false` if anything fails. ### PSR-3 Support -The recommended approach of logging is to use a [PSR-3](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md) compliant logger implementing `Psr\Log\LoggerInterface`. The `Pusher` object implements `Psr\Log\LoggerAwareInterface`, meaning you call `setLogger(LoggerInterface $logger)` to set the logger instance. +The recommended approach of logging is to use a +[PSR-3](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md) +compliant logger implementing `Psr\Log\LoggerInterface`. The `Pusher` object +implements `Psr\Log\LoggerAwareInterface`, meaning you call +`setLogger(LoggerInterface $logger)` to set the logger instance. ```php // where $logger implements `LoggerInterface` @@ -97,9 +118,12 @@ $pusher->setLogger($logger); ### Custom Logger (deprecated) -> **Warning**: Using `Pusher::set_logger()` and a custom object implementing `log()` is now deprecated and will be removed in the future. Please use a PSR-3 compliant logger. +> **Warning**: Using `Pusher::set_logger()` and a custom object implementing +> `log()` is now deprecated and will be removed in the future. Please use a +> PSR-3 compliant logger. -You set up logging by passing an object with a `log` function to the `pusher->set_logger` function: +You set up logging by passing an object with a `log` function to the +`pusher->set_logger` function: ```php class MyLogger { @@ -111,7 +135,9 @@ class MyLogger { $pusher->set_logger( new MyLogger() ); ``` -If you use the above example in code executed from the console/terminal the debug information will be output there. If you use this within a web app then the output will appear within the generated app output e.g. HTML. +If you use the above example in code executed from the console/terminal the +debug information will be output there. If you use this within a web app then +the output will appear within the generated app output e.g. HTML. ## Publishing/Triggering events @@ -160,7 +186,9 @@ The output of this will be: ### Socket id -In order to avoid duplicates you can optionally specify the sender's socket id while triggering an event ([https://pusher.com/docs/duplicates](http://pusherapp.com/docs/duplicates)): +In order to avoid duplicates you can optionally specify the sender's socket id +while triggering an event +([https://pusher.com/docs/duplicates](http://pusherapp.com/docs/duplicates)): ```php $pusher->trigger('my-channel','event','data','socket_id'); @@ -168,7 +196,8 @@ $pusher->trigger('my-channel','event','data','socket_id'); ### JSON format -If your data is already encoded in JSON format, you can avoid a second encoding step by setting the sixth argument true, like so: +If your data is already encoded in JSON format, you can avoid a second encoding +step by setting the sixth argument true, like so: ```php $pusher->trigger('my-channel', 'event', 'data', null, false, true) @@ -176,7 +205,8 @@ $pusher->trigger('my-channel', 'event', 'data', null, false, true) ## Authenticating Private channels -To authorise your users to access private channels on Pusher, you can use the socket_auth function: +To authorise your users to access private channels on Pusher, you can use the +`socket_auth` function: ```php $pusher->socket_auth('private-my-channel','socket_id'); @@ -184,7 +214,8 @@ $pusher->socket_auth('private-my-channel','socket_id'); ## Authenticating Presence channels -Using presence channels is similar to private channels, but you can specify extra data to identify that particular user: +Using presence channels is similar to private channels, but you can specify +extra data to identify that particular user: ```php $pusher->presence_auth('presence-my-channel','socket_id', 'user_id', 'user_info'); @@ -192,7 +223,12 @@ $pusher->presence_auth('presence-my-channel','socket_id', 'user_id', 'user_info' ## Webhooks -This library provides a way of verifying that webhooks you receive from Pusher are actually genuine webhooks from Pusher. It also provides a structure for storing them. A helper method called `webhook` enables this. Pass in the headers and body of the request, and it'll return a Webhook object with your verified events. If the library was unable to validate the signature, an exception is thrown instead. +This library provides a way of verifying that webhooks you receive from Pusher +are actually genuine webhooks from Pusher. It also provides a structure for +storing them. A helper method called `webhook` enables this. Pass in the +headers and body of the request, and it'll return a Webhook object with your +verified events. If the library was unable to validate the signature, an +exception is thrown instead. ```php $webhook = $pusher->webhook($request_headers, $request_body); @@ -202,30 +238,53 @@ $time_recieved = $webhook->get_time_ms(); ## End to end encryption (beta) -This library supports end to end encryption of your private channels. This means that only you and your connected clients will be able to read your messages. Pusher cannot decrypt them. You can enable this feature by following these steps: -1. You should first set up Private channels. This involves [creating an authentication endpoint on your server](https://pusher.com/docs/authenticating_users). -2. Next, Specify your 32 character `encryption_master_key`. This is secret and you should never share this with anyone. Not even Pusher. +This library supports end to end encryption of your private channels. This +means that only you and your connected clients will be able to read your +messages. Pusher cannot decrypt them. You can enable this feature by following +these steps: -```php -$app_id = 'YOUR_APP_ID'; -$app_key = 'YOUR_APP_KEY'; -$app_secret = 'YOUR_APP_SECRET'; -$app_cluster = 'YOUR_APP_CLUSTER'; -$encryption_master_key = "abcdefghijklmnopqrstuvwxyzabcdef"; -$pusher = new Pusher\Pusher($app_key, $app_secret, $app_id, array( - 'cluster' => $app_cluster, - 'encryption_master_key' => $encryption_master_key - ) -); -``` +1. You should first set up Private channels. This involves [creating an + authentication endpoint on your + server](https://pusher.com/docs/authenticating_users). + +2. Next, generate your 32 byte master encryption key, base64 encode it and + store it securely. This is secret and you should never share this with + anyone. Not even Pusher. + + To generate an appropriate key from a good random source, you can use the + `openssl` command: + + ```sh + openssl rand -base64 32 + ``` + +3. Specify your master encryption key when creating your Pusher client: + + ```php + $pusher = new Pusher\Pusher( + $app_key, + $app_secret, + $app_id, + array( + 'cluster' => $app_cluster, + 'encryption_master_key_base64' => "" + ) + ); + ``` -3. Channels where you wish to use end to end encryption should be prefixed with `private-encrypted-`. +4. Channels where you wish to use end to end encryption should be prefixed with + `private-encrypted-`. -4. Subscribe to these channels in your client, and you're done! You can verify it is working by checking out the debug console on the [https://dashboard.pusher.com/](dashboard) and seeing the scrambled ciphertext. +5. Subscribe to these channels in your client, and you're done! You can verify + it is working by checking out the debug console on the + [https://dashboard.pusher.com/](dashboard) and seeing the scrambled + ciphertext. -**Important note: This will __not__ encrypt messages on channels that are not prefixed by `private-encrypted-`.** +**Important note: This will __not__ encrypt messages on channels that are not +prefixed by `private-encrypted-`.** -**Limitation**: you cannot trigger a single event on multiple channels in a call to `trigger`, e.g. +**Limitation**: you cannot trigger a single event on multiple channels in a +call to `trigger`, e.g. ```php $data['name'] = 'joe'; @@ -234,7 +293,11 @@ $data['message_count'] = 23; $pusher->trigger(array('channel-1', 'private-encrypted-channel-2'), 'test_event', $data); ``` -Rationale: the methods in this library map directly to individual Channels HTTP API requests. If we allowed triggering a single event on multiple channels (some encrypted, some unencrypted), then it would require two API requests: one where the event is encrypted to the encrypted channels, and one where the event is unencrypted for unencrypted channels. +Rationale: the methods in this library map directly to individual Channels HTTP +API requests. If we allowed triggering a single event on multiple channels +(some encrypted, some unencrypted), then it would require two API requests: one +where the event is encrypted to the encrypted channels, and one where the event +is unencrypted for unencrypted channels. ### Presence example @@ -265,7 +328,9 @@ $presence_data = array('name' => $user['name']); echo $pusher->presence_auth($_POST['channel_name'], $_POST['socket_id'], $user['id'], $presence_data); ``` -Note: this assumes that you store your users in a table called `users` and that those users have a `name` column. It also assumes that you have a login mechanism that stores the `user_id` of the logged in user in the session. +Note: this assumes that you store your users in a table called `users` and that +those users have a `name` column. It also assumes that you have a login +mechanism that stores the `user_id` of the logged in user in the session. ## Application State Queries @@ -282,14 +347,18 @@ $info = $pusher->get_channel_info('channel-name'); $channel_occupied = $info->occupied; ``` -For [presence channels](https://pusher.com/docs/presence_channels) you can also query the number of distinct users currently subscribed to this channel (a single user may be subscribed many times, but will only count as one): +For [presence channels](https://pusher.com/docs/presence_channels) you can also +query the number of distinct users currently subscribed to this channel (a +single user may be subscribed many times, but will only count as one): ```php $info = $pusher->get_channel_info('presence-channel-name', array('info' => 'user_count')); $user_count = $info->user_count; ``` -If you have enabled the ability to query the `subscription_count` (the number of connections currently subscribed to this channel) then you can query this value as follows: +If you have enabled the ability to query the `subscription_count` (the number +of connections currently subscribed to this channel) then you can query this +value as follows: ```php $info = $pusher->get_channel_info('presence-channel-name', array('info' => 'subscription_count')); @@ -302,7 +371,8 @@ $subscription_count = $info->subscription_count; $pusher->get_channels() ``` -It's also possible to get a list of channels for an application from the Channels HTTP API. +It's also possible to get a list of channels for an application from the +Channels HTTP API. ```php $result = $pusher->get_channels(); @@ -315,7 +385,10 @@ $channel_count = count($result->channels); // $channels is an Array $pusher->get_channels( array( 'filter_by_prefix' => 'some_filter' ) ) ``` -It's also possible to get a list of channels based on their name prefix. To do this you need to supply an $options parameter to the call. In the following example the call will return a list of all channels with a 'presence-' prefix. This is idea for fetching a list of all presence channels. +It's also possible to get a list of channels based on their name prefix. To do +this you need to supply an `$options` parameter to the call. In the following +example the call will return a list of all channels with a `presence-` prefix. +This is idea for fetching a list of all presence channels. ```php $results = $pusher->get_channels( array( 'filter_by_prefix' => 'presence-') ); @@ -330,7 +403,10 @@ $pusher->get( '/channels', array( 'filter_by_prefix' => 'presence-' ) ); ### Get a list of application channels with subscription counts -The HTTP API returning the channel list does not support returning the subscription count along with each channel. Instead, you can fetch this data by iterating over each channel and making another request. But be warned: this approach consumes (number of channels + 1) messages! +The HTTP API returning the channel list does not support returning the +subscription count along with each channel. Instead, you can fetch this data by +iterating over each channel and making another request. But be warned: this +approach consumes (number of channels + 1) messages! ```php get( '/channels/presence-channel-name/users' ) The `$response` is in the format: ```php -Array -( +Array ( [body] => {"users":[{"id":"a_user_id"}]} [status] => 200 - [result] => Array - ( - [users] => Array - ( - [0] => Array - ( - [id] => a_user_id - ) - /* Additional users */ - ) + [result] => Array ( + [users] => Array ( + [0] => Array ( + [id] => a_user_id + ), + /* Additional users */ ) + ) ) ``` @@ -385,7 +457,10 @@ $pusher->get( $path, $params ); Used to make `GET` queries against the Channels HTTP API. Handles authentication. -Response is an associative array with a `result` index. The contents of this index is dependent on the HTTP method that was called. However, a `status` property to allow the HTTP status code is always present and a `result` property will be set if the status code indicates a successful call to the API. +Response is an associative array with a `result` index. The contents of this +index is dependent on the HTTP method that was called. However, a `status` +property to allow the HTTP status code is always present and a `result` +property will be set if the status code indicates a successful call to the API. ```php $response = $pusher->get( '/channels' ); @@ -398,11 +473,15 @@ $result = $response[ 'result' ]; Requires [phpunit](https://github.com/sebastianbergmann/phpunit). * Run `composer install` -* Go to the `test` directory -* Rename `config.example.php` and replace the values with valid Channels credentials **or** create environment variables. -* Some tests require a client to be connected to the app you defined in the config; - you can do this by opening https://dashboard.pusher.com/apps//getting_started in the browser -* From the root directory of the project, execute `composer exec phpunit` to run all the tests. +* Go to the `tests` directory +* Rename `config.example.php` and replace the values with valid Channels + credentials **or** create environment variables. +* Some tests require a client to be connected to the app you defined in the + config; you can do this by opening + https://dashboard.pusher.com/apps//getting_started in the + browser +* From the root directory of the project, execute `composer exec phpunit` to + run all the tests. ## License