Permalink
Browse files

initial commit

  • Loading branch information...
0 parents commit 96f4b5f8d698abe07cc8b1a914cb9161c09644c4 @igorw committed Dec 31, 2011
Showing with 336 additions and 0 deletions.
  1. +19 −0 LICENSE
  2. +78 −0 README.md
  3. +21 −0 composer.json
  4. +108 −0 src/Igorw/EventSource/Event.php
  5. +48 −0 src/Igorw/EventSource/EventWrapper.php
  6. +62 −0 src/Igorw/EventSource/Stream.php
19 LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2011 Igor Wiedler
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
@@ -0,0 +1,78 @@
+# EventSource
+
+A PHP 5.3 library for creating an [EventSource](http://dev.w3.org/html5/eventsource/) stream.
+
+EventSource or Server-Sent-Events is a W3C specification that defines a protocol and an API
+for pushing data from the server to the client. This library is a server-side implementation
+of this protocol.
+
+It is designed to be transport agnostic, allowing you to use it with apache directly or with
+other webservers, such as mongrel2.
+
+## Fetch
+
+The recommended way to install EventSource is [through composer](http://packagist.org).
+
+Just create a composer.json file for your project:
+
+ {
+ "require": {
+ "igorw/event-source": "*"
+ }
+ }
+
+And run these two commands to install it:
+
+ $ wget http://getcomposer.org/composer.phar
+ $ php composer.phar install
+
+Now you can add the autoloader, and you will have access to the library:
+
+```php
+<?php
+require 'vendor/.composer/autoload.php';
+```
+
+## Usage
+
+```php
+<?php
+
+use Igorw\EventSource\Stream;
+
+foreach (Stream::getHeaders() as $name => $value) {
+ header("$name: $value");
+}
+
+$handler = function ($chunk) {
+ echo $chunk;
+ ob_flush();
+ flush();
+};
+
+$stream = new Stream($handler);
+
+while (true) {
+ $stream
+ ->event()
+ ->setData("Hello World")
+ ->end()
+ ->flush();
+
+ sleep(2);
+}
+```
+
+And an example JavaScript client:
+
+```JavaScript
+var stream = new EventSource('stream.php');
+
+stream.addEventListener('message', function (event) {
+ console.log(event.data);
+});
+```
+
+License
+-------
+MIT, see LICENSE.
@@ -0,0 +1,21 @@
+{
+ "name": "igorw/event-source",
+ "type": "library",
+ "description": "A PHP 5.3 library for creating an EventSource stream.",
+ "keywords": ["event-source", "server-sent-events", "real-time"],
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Igor Wiedler",
+ "email": "igor@wiedler.ch"
+ }
+ ],
+ "require": {
+ "php": ">=5.3.0"
+ },
+ "autoload": {
+ "psr-0": {
+ "Igorw\\EventSource": "src"
+ }
+ }
+}
@@ -0,0 +1,108 @@
+<?php
+
+/*
+ * This file is part of EventSource.
+ *
+ * (c) Igor Wiedler <igor@wiedler.ch>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Igorw\EventSource;
+
+class Event
+{
+ private $comments = array();
+ private $id;
+ private $event;
+ private $data = array();
+
+ public function addComment($comment)
+ {
+ $this->comments = array_merge(
+ $this->comments,
+ $this->extractNewlines($comment)
+ );
+
+ return $this;
+ }
+
+ public function setId($id = null)
+ {
+ $this->id = $id;
+
+ return $this;
+ }
+
+ public function setEvent($event = null)
+ {
+ $this->event = $event;
+
+ return $this;
+ }
+
+ public function setData($data)
+ {
+ $this->data = $this->extractNewlines($data);
+
+ return $this;
+ }
+
+ public function appendData($data)
+ {
+ $this->data = array_merge(
+ $this->data,
+ $this->extractNewlines($data)
+ );
+
+ return $this;
+ }
+
+ public function dump()
+ {
+ $response = $this->getFormattedComments().
+ $this->getFormattedId().
+ $this->getFormattedEvent().
+ $this->getFormattedData();
+
+ return '' !== $response ? $response."\n" : '';
+ }
+
+ public function getFormattedComments()
+ {
+ return $this->formatLines('', $this->comments);
+ }
+
+ public function getFormattedId()
+ {
+ return $this->formatLines('id', $this->id);
+ }
+
+ public function getFormattedEvent()
+ {
+ return $this->formatLines('event', $this->event);
+ }
+
+ public function getFormattedData()
+ {
+ return $this->formatLines('data', $this->data);
+ }
+
+ private function extractNewlines($input)
+ {
+ return explode("\n", $input);
+ }
+
+ private function formatLines($key, $lines)
+ {
+ $formatted = array_map(
+ function ($line) use ($key) {
+ return $key.': '.$line."\n";
+ },
+ (array) $lines
+ );
+
+ return implode('', $formatted);
+ }
+}
@@ -0,0 +1,48 @@
+<?php
+
+/*
+ * This file is part of EventSource.
+ *
+ * (c) Igor Wiedler <igor@wiedler.ch>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Igorw\EventSource;
+
+class EventWrapper
+{
+ private $event;
+ private $source;
+
+ public function __construct(Event $event, \Closure $source = null)
+ {
+ $this->event = $event;
+ $this->source = $source;
+ }
+
+ public function getWrappedEvent()
+ {
+ return $this->event;
+ }
+
+ public function end()
+ {
+ if ($this->source) {
+ return call_user_func($this->source);
+ }
+ }
+
+ public function __call($name, $args)
+ {
+ $method = array($this->event, $name);
+ $value = call_user_func_array($method, $args);
+
+ if ($this->event === $value) {
+ return $this;
+ }
+
+ return $value;
+ }
+}
@@ -0,0 +1,62 @@
+<?php
+
+/*
+ * This file is part of EventSource.
+ *
+ * (c) Igor Wiedler <igor@wiedler.ch>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Igorw\EventSource;
+
+/**
+ * Generates a stream in the W3C EventSource format
+ * http://dev.w3.org/html5/eventsource/
+ */
+class Stream
+{
+ private $buffer;
+ private $handler;
+
+ public function __construct(\Closure $handler)
+ {
+ $this->buffer = new \SplQueue();
+ $this->buffer->setIteratorMode(\SplQueue::IT_MODE_DELETE);
+ $this->handler = $handler;
+ }
+
+ public function event()
+ {
+ $event = new Event();
+ $this->buffer->enqueue($event);
+
+ $that = $this;
+
+ $wrapper = new EventWrapper($event, function () use ($that) {
+ return $that;
+ });
+
+ return $wrapper;
+ }
+
+ public function flush()
+ {
+ foreach ($this->buffer as $event) {
+ $chunk = $event->dump();
+ if ('' !== $chunk) {
+ call_user_func($this->handler, $chunk);
+ }
+ }
+ }
+
+ static public function getHeaders()
+ {
+ return array(
+ 'Content-Type' => 'text/event-stream',
+ 'Transfer-Encoding' => 'identity',
+ 'Cache-Control' => 'no-cache',
+ );
+ }
+}

0 comments on commit 96f4b5f

Please sign in to comment.