3 * StatusNet - the distributed open-source microblogging tool
4 * Copyright (C) 2011, StatusNet, Inc.
6 * A channel for real-time browser data
10 * This program is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU Affero General Public License as published by
12 * the Free Software Foundation, either version 3 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Affero General Public License for more details.
20 * You should have received a copy of the GNU Affero General Public License
21 * along with this program. If not, see <http://www.gnu.org/licenses/>.
25 * @author Evan Prodromou <evan@status.net>
26 * @copyright 2011 StatusNet, Inc.
27 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
28 * @link http://status.net/
31 if (!defined('STATUSNET')) {
36 * A channel for real-time browser data
38 * For each user currently browsing the site, we want to know which page they're on
39 * so we can send real-time updates to their browser.
43 * @author Evan Prodromou <evan@status.net>
44 * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
45 * @link http://status.net/
49 class Realtime_channel extends Managed_DataObject
51 const TIMEOUT = 1800; // 30 minutes
53 public $__table = 'realtime_channel'; // table name
55 public $user_id; // int -> user.id, can be null
56 public $action; // string
57 public $arg1; // argument
58 public $arg2; // argument, usually null
59 public $channel_key; // 128-bit shared secret key
60 public $audience; // listener count
61 public $created; // created date
62 public $modified; // modified date
65 * The One True Thingy that must be defined and declared.
67 public static function schemaDef()
70 'description' => 'A channel of realtime notice data',
72 'user_id' => array('type' => 'int',
74 'description' => 'user viewing page; can be null'),
75 'action' => array('type' => 'varchar',
78 'description' => 'page being viewed'),
79 'arg1' => array('type' => 'varchar',
82 'description' => 'page argument, like username or tag'),
83 'arg2' => array('type' => 'varchar',
86 'description' => 'second page argument, like tag for showstream'),
87 'channel_key' => array('type' => 'varchar',
90 'description' => 'shared secret key for this channel'),
91 'audience' => array('type' => 'integer',
94 'description' => 'reference count'),
95 'created' => array('type' => 'datetime',
97 'description' => 'date this record was created'),
98 'modified' => array('type' => 'datetime',
100 'description' => 'date this record was modified'),
102 'primary key' => array('channel_key'),
103 'unique keys' => array('realtime_channel_user_page_idx' => array('user_id', 'action', 'arg1', 'arg2')),
104 'foreign keys' => array(
105 'realtime_channel_user_id_fkey' => array('user', array('user_id' => 'id')),
108 'realtime_channel_modified_idx' => array('modified'),
109 'realtime_channel_page_idx' => array('action', 'arg1', 'arg2')
114 static function saveNew($user_id, $action, $arg1, $arg2)
116 $channel = new Realtime_channel();
118 $channel->user_id = $user_id;
119 $channel->action = $action;
120 $channel->arg1 = $arg1;
121 $channel->arg2 = $arg2;
122 $channel->audience = 1;
124 $channel->channel_key = common_random_hexstr(16); // 128-bit key, 32 hex chars
126 $channel->created = common_sql_now();
127 $channel->modified = $channel->created;
134 static function getChannel($user_id, $action, $arg1, $arg2)
136 $channel = self::fetchChannel($user_id, $action, $arg1, $arg2);
138 // Ignore (and delete!) old channels
140 if (!empty($channel)) {
141 $modTime = strtotime($channel->modified);
142 if ((time() - $modTime) > self::TIMEOUT) {
148 if (empty($channel)) {
149 $channel = self::saveNew($user_id, $action, $arg1, $arg2);
155 static function getAllChannels($action, $arg1, $arg2)
157 $channel = new Realtime_channel();
159 $channel->action = $action;
161 if (is_null($arg1)) {
162 $channel->whereAdd('arg1 is null');
164 $channel->arg1 = $arg1;
167 if (is_null($arg2)) {
168 $channel->whereAdd('arg2 is null');
170 $channel->arg2 = $arg2;
173 $channel->whereAdd('modified > "' . common_sql_date(time() - self::TIMEOUT) . '"');
177 if ($channel->find()) {
178 $channels = $channel->fetchAll();
184 static function fetchChannel($user_id, $action, $arg1, $arg2)
186 $channel = new Realtime_channel();
188 if (is_null($user_id)) {
189 $channel->whereAdd('user_id is null');
191 $channel->user_id = $user_id;
194 $channel->action = $action;
196 if (is_null($arg1)) {
197 $channel->whereAdd('arg1 is null');
199 $channel->arg1 = $arg1;
202 if (is_null($arg2)) {
203 $channel->whereAdd('arg2 is null');
205 $channel->arg2 = $arg2;
208 if ($channel->find(true)) {
209 $channel->increment();
219 $orig = clone($this);
221 $this->modified = common_sql_now();
222 $this->update($orig);
228 $orig = clone($this);
229 $this->modified = common_sql_now();
230 $this->update($orig);
236 if ($this->audience == 1) {
239 $orig = clone($this);
241 $this->modified = common_sql_now();
242 $this->update($orig);