Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
0.00% |
0 / 88 |
n/a |
0 / 0 |
CRAP | n/a |
0 / 0 |
||
| 1 | <?php |
| 2 | // include the ably library |
| 3 | require_once __DIR__ . '/../vendor/autoload.php'; |
| 4 | // if not using composer, use this include instead: |
| 5 | // require_once __DIR__ . '/../ably-loader.php'; |
| 6 | |
| 7 | $apiKey = getenv( 'ABLY_KEY' ); // private api key |
| 8 | $host = getenv( 'ABLY_HOST' ); // ably server |
| 9 | $wshost = getenv( 'ABLY_WS_HOST' ); // ably websocket server |
| 10 | |
| 11 | if (!$apiKey) { |
| 12 | die( 'Please provide your Ably key as an environment variable ABLY_KEY.' ); |
| 13 | } |
| 14 | |
| 15 | $channelName = isset($_REQUEST['channel']) ? $_REQUEST['channel'] : 'persist:chat'; |
| 16 | $eventName = isset($_REQUEST['event']) ? $_REQUEST['event'] : 'guest'; |
| 17 | $settings = array( |
| 18 | 'key' => $apiKey, |
| 19 | ); |
| 20 | |
| 21 | if ($host) { |
| 22 | $settings['host'] = $host; |
| 23 | } |
| 24 | |
| 25 | // instantiate Ably |
| 26 | $app = new \Ably\AblyRest($settings); |
| 27 | $channel = $app->channel($channelName); |
| 28 | |
| 29 | if (!empty($_POST)) { |
| 30 | // publish a message |
| 31 | $channel->publish( $eventName, array('handle' => $_POST['handle'], 'message' => $_POST['message']) ); |
| 32 | die(); |
| 33 | } |
| 34 | |
| 35 | // get a list of recent messages and render the interface |
| 36 | $messages = $channel->history( array('direction' => 'backwards') )->items; |
| 37 | |
| 38 | ?> |
| 39 | <!DOCTYPE HTML> |
| 40 | <html lang="en-US"> |
| 41 | <head> |
| 42 | <meta charset="UTF-8"> |
| 43 | <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1; user-scalable=no"> |
| 44 | <title>Simple Chat Demo</title> |
| 45 | <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css"> |
| 46 | <style> |
| 47 | body { padding: 10px; overflow: hidden; background: url(//d6i46dwqrtafp.cloudfront.net/images/bg/carbon_fibre.png) } |
| 48 | .chat-window { overflow: hidden; border-top: 1px solid #e1e1e1; position: relative; } |
| 49 | .chat-window-content { overflow: auto; color: #888; height: 500px; } |
| 50 | .chat-window-content > ul { list-style: none; margin: 25px 0 50px; padding: 0; } |
| 51 | .chat-window-shadow { position: absolute; z-index: 100; height: 50px; width: 100%; } |
| 52 | .chat-window-shadow-top { top: 0; background-image: -webkit-linear-gradient(top, rgba(255,255,255, 1), rgba(255,255,255, 0)) } |
| 53 | .chat-window-shadow-bottom { bottom: 0; background-image: -webkit-linear-gradient(bottom, rgba(255,255,255, 1), rgba(255,255,255, 0)) } |
| 54 | .handle { color: #2f91ff; font-weight: bold } |
| 55 | .time { float: right; color: #ccc; } |
| 56 | h1.panel-title small { font-size: 12px; } |
| 57 | </style> |
| 58 | </head> |
| 59 | <body> |
| 60 | |
| 61 | <div class="panel panel-default"> |
| 62 | <div class="panel-heading"> |
| 63 | <h1 class="panel-title">Let's Chat <small>[api_time: <?php echo gmdate('r', $app->time()/1000) ?> | server_time: <?php echo gmdate('r', time()) ?>]</small></h1> |
| 64 | </div> |
| 65 | <div class="panel-body"> |
| 66 | <form id="message_form" method="post" action="index.php" class="form-inline" role="form"> |
| 67 | <input type="hidden" name="channel" value="<?= $channelName ?>"> |
| 68 | <input type="hidden" name="event" value="<?= $eventName ?>"> |
| 69 | <div id="form-group-handle" class="form-group"> |
| 70 | <input type="text" name="handle" class="form-control input-sm" placeholder="Your handle"> |
| 71 | </div> |
| 72 | <div class="form-group"> |
| 73 | <input type="text" name="message" class="form-control input-sm" placeholder="Say something"> |
| 74 | </div> |
| 75 | <button id="rest" type="button" class="btn btn-default btn-sm">Send via PHP REST</button> |
| 76 | <button id="realtime" type="button" class="btn btn-default btn-sm">Send via JS realtime</button> |
| 77 | <button id="resetHandle" type="button" class="btn btn-default btn-sm">Reset Handle</button> |
| 78 | </form> |
| 79 | </div> |
| 80 | <div class="chat-window list-group"> |
| 81 | <div class="chat-window-content"> |
| 82 | <ul id="message_pool"> |
| 83 | <?php $date_format = 'D jS F, Y'; $stamp = date($date_format, time()); ?> |
| 84 | <?php foreach ($messages as $message): ?> |
| 85 | <?php if (property_exists($message, 'data')) : |
| 86 | $timestamp = intval($message->timestamp / 1000); |
| 87 | $day = date($date_format, $timestamp); ?> |
| 88 | <?php if ($stamp != $day) : ?> |
| 89 | <li class="list-group-item"><h2 class="h4"><?= $day ?></h2></li> |
| 90 | <?php $stamp = $day; endif; ?> |
| 91 | <li class="list-group-item"><span class="time"><?= gmdate('h:i a', $timestamp) ?></span> |
| 92 | <b class="handle"><?= $message->data->handle ?>:</b> <?= $message->data->message ?></li> |
| 93 | <?php endif; endforeach; ?> |
| 94 | </ul> |
| 95 | <div class="chat-window-shadow chat-window-shadow-top"></div> |
| 96 | <div class="chat-window-shadow chat-window-shadow-bottom"></div> |
| 97 | </div> |
| 98 | </div> |
| 99 | </div> |
| 100 | |
| 101 | <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script> |
| 102 | <script src="//cdn.ably.io/lib/ably.js"></script> |
| 103 | <script type="text/javascript"> |
| 104 | |
| 105 | (function($) { |
| 106 | |
| 107 | var $handle = $('#form-group-handle input'); |
| 108 | |
| 109 | var showStoredHandle = function(){ |
| 110 | if(localStorage.handle){ |
| 111 | $handle.val(localStorage.handle).hide(); |
| 112 | if (!$handle.siblings('label').length) { |
| 113 | $handle.parent().append('<label>'+localStorage.handle+'</label>'); |
| 114 | } |
| 115 | |
| 116 | } |
| 117 | } |
| 118 | |
| 119 | showStoredHandle(); |
| 120 | |
| 121 | // adjust chat window height |
| 122 | var $chatWindowContent = $('.chat-window-content'); |
| 123 | |
| 124 | $(window).on('resize', function() { |
| 125 | $chatWindowContent.height($(this).height() - $chatWindowContent.offset().top - 10); |
| 126 | }).resize(); |
| 127 | |
| 128 | var ably = new Ably.Realtime({ |
| 129 | key: '<?= $apiKey ?>', |
| 130 | tls: true, |
| 131 | log: {level:4} |
| 132 | <?php if ($host): ?>,host: '<?= $host ?>'<?php endif; ?> |
| 133 | <?php if ($wshost): ?>,wsHost: '<?= $wshost ?>'<?php endif; ?> |
| 134 | }); |
| 135 | |
| 136 | var channel = ably.channels.get('<?= $channelName ?>'); |
| 137 | |
| 138 | channel.subscribe('<?= $eventName ?>', function(response) { |
| 139 | var data = response.data; |
| 140 | var timestamp = response.timestamp |
| 141 | var d = new Date( timestamp.toString().length > 10 ? timestamp : timestamp*1000 ); |
| 142 | var hours = d.getUTCHours(); |
| 143 | var ampm = hours > 12 ? ' pm' : ' am'; |
| 144 | hours = hours % 12; |
| 145 | hours = hours === 0 ? 12 : hours; |
| 146 | var minutes = ('0'+d.getUTCMinutes()).substr(-2); |
| 147 | var post_time = [hours, minutes].join(':') + ampm; |
| 148 | $('#message_pool').prepend( |
| 149 | '<li class="list-group-item"><span class="label label-danger">received</span> <time>'+ |
| 150 | post_time +'</time> <b class="handle">'+ data.handle +':</b> '+ data.message +'</li>' |
| 151 | ); |
| 152 | }); |
| 153 | |
| 154 | function sendMessage(mode) { |
| 155 | var $form = $('#message_form'), |
| 156 | broadcast = true, |
| 157 | $handle = $('[name="handle"]', $form), |
| 158 | $message = $('[name="message"]', $form); |
| 159 | |
| 160 | if ($.trim($handle.val()) === '') { |
| 161 | alert('you must provide a handle'); |
| 162 | $handle.focus(); |
| 163 | broadcast = false; |
| 164 | } |
| 165 | else { |
| 166 | localStorage.handle = $handle.val(); |
| 167 | showStoredHandle(); |
| 168 | } |
| 169 | |
| 170 | if ($.trim($message.val()) === '') { |
| 171 | alert('you must type a message'); |
| 172 | $message.focus(); |
| 173 | broadcast = false; |
| 174 | } |
| 175 | |
| 176 | if (broadcast) { |
| 177 | if (mode === 'realtime') { |
| 178 | channel.publish('<?= $eventName ?>', { handle: $handle.val(), message: $message.val() } ); |
| 179 | $message.val(''); |
| 180 | } else { |
| 181 | $.ajax({ |
| 182 | url: $form[0].action, |
| 183 | data: $form.serialize(), |
| 184 | type: $form[0].method, |
| 185 | dataType: 'json', |
| 186 | complete: function() { |
| 187 | $message.val(''); |
| 188 | } |
| 189 | }); |
| 190 | } |
| 191 | } |
| 192 | } |
| 193 | |
| 194 | $('#rest').on('click', function() { |
| 195 | sendMessage('rest'); |
| 196 | return false; |
| 197 | }); |
| 198 | |
| 199 | $('#realtime').on('click', function() { |
| 200 | sendMessage('realtime'); |
| 201 | return false; |
| 202 | }); |
| 203 | $('#resetHandle').on('click', function() { |
| 204 | localStorage.removeItem('handle'); |
| 205 | $handle.siblings('label').remove().end().val('').fadeIn(); |
| 206 | }); |
| 207 | |
| 208 | })(jQuery); |
| 209 | </script> |
| 210 | |
| 211 | </body> |
| 212 | </html> |