Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 88
n/a
0 / 0
CRAP
n/a
0 / 0
1<?php
2// include the ably library
3require_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
11if (!$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
21if ($host) {
22    $settings['host'] = $host;
23}
24
25// instantiate Ably
26$app = new \Ably\AblyRest($settings);
27$channel = $app->channel($channelName);
28
29if (!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>