function Streams_0_9_3_Streams() { $results = Streams_Participant::select("publisherId, streamName, COUNT(IF(state='invited', 1, NULL)) invitedCount, COUNT(IF(state='participating', 1, NULL)) participatingCount, COUNT(IF(state='left', 1, NULL)) leftCount")->groupBy('publisherId, streamName')->fetchAll(PDO::FETCH_ASSOC); echo "Updating streams..."; $c = count($results); $i = 0; foreach ($results as $r) { Streams_Stream::update()->set(array('invitedCount' => intval($r['invitedCount']), 'participatingCount' => intval($r['participatingCount']), 'leftCount' => intval($r['leftCount'])))->where(array('publisherId' => $r['publisherId'], 'name' => $r['streamName']))->execute(); ++$i; echo "[100D"; echo "Updated {$i} of {$c} streams"; } echo "\n"; }
/** * Fetch participants of the stream. * @method getParticipants * @param {array} [options=array()] An array of options determining how messages will be fetched, which can include: * "state" => One of "invited", "participating", "left" * Can also be negative, then the value will be substracted from maximum number of existing messages and +1 will be added * to guarantee that $max = -1 means highest message ordinal. * "limit" => Number of the participants to be selected. Defaults to 1000. * "offset" => Number of the messages to be selected. Defaults to 1000. * "ascending" => Sorting of fetched participants by insertedTime. If true, sorting is ascending, if false - descending. Defaults to false. * "type" => Optional string specifying the particular type of messages to get */ function getParticipants($options) { $criteria = array('publisherId' => $this->publisherId, 'streamName' => $this->name); if (isset($options['state'])) { $possible_states = array('invited', 'participating', 'left'); if (!in_array($options['state'], $possible_states)) { throw new Q_Exception_WrongValue(array('field' => 'state', 'range' => '"' . implode('", "', $possible_states) . '"')); } $criteria['state'] = $options['state']; } $q = Streams_Participant::select('*')->where($criteria); $ascending = false; if (empty($options['limit'])) { $options['limit'] = 1000; } $limit = isset($options['limit']) ? $options['limit'] : null; $offset = isset($options['offset']) ? $options['offset'] : 0; if (isset($limit)) { $q->limit($options['limit'], $offset); } $q->orderBy('insertedTime', isset($options['ascending']) ? $options['ascending'] : $ascending); return $q->fetchDbRows(null, '', 'userId'); }
/** * Filter out users which are or are not participants * @method filter * @static * @param {array} $userIds * @param {Streams_Stream} $stream * @param {boolean} $participate=false * @return {array} */ static function filter($userIds, $stream, $participate = false) { $p = array_keys(Streams_Participant::select('*')->where(array('publisherId' => $stream->publisherId, 'streamName' => $stream->name, 'userId' => $userIds, 'state' => 'participating'))->fetchDbRows(null, '', 'userId')); return $participate ? $p : array_diff($userIds, $p); }
/** * Unsubscribe from one or more streams, to stop receiving notifications. * Pooststs "Streams/unsubscribe" message to the streams. * Also posts "Streams/unsubscribed" messages to user's "Streams/participating" stream. * Does not change the actual subscription, but only the participant row. * (When subscribing again, the existing subscription will be used.) * @method unsubscribe * @static * @param {string} $asUserId The id of the user that is joining. Pass null here to use the logged-in user's id. * @param {string} $publisherId The id of the user publishing all the streams * @param {array} $streams An array of Streams_Stream objects or stream names * @param {array} [$options=array()] * @param {boolean} [$options.leave] set to true to also leave the streams * @param {boolean} [$options.skipAccess] if true, skip access check for whether user can join and subscribe * @return {array} Returns an array of Streams_Participant rows, if any were in the database. */ static function unsubscribe($asUserId, $publisherId, $streams, $options = array()) { $streams2 = self::_getStreams($asUserId, $publisherId, $streams); $streamNames = array(); foreach ($streams2 as $s) { $streamNames[] = $s->name; } if (empty($options['skipAccess'])) { self::_accessExceptions($streams2, $streamNames, 'join'); } $skipAccess = Q::ifset($options, 'skipAccess', false); if (empty($options['leave'])) { $criteria = array('publisherId' => $publisherId, 'streamName' => $streamNames, 'userId' => $asUserId); Streams_Participant::update()->set(array('subscribed' => 'no'))->where($criteria)->execute(); $participants = Streams_Participant::select('*')->where($criteria)->fetchDbRows(); } else { $participants = Streams::leave($asUserId, $publisherId, $streams2, compact('skipAccess')); } $messages = array(); $pMessages = array(); foreach ($streamNames as $sn) { $stream = $streams2[$sn]; if ($participant = Q::ifset($participants, $sn, null)) { if ($participant instanceof Streams_Participant) { $participant = $participant->toArray(); } } // Send a message to Node Q_Utils::sendToNode(array("Q/method" => "Streams/Stream/unsubscribe", "participant" => Q::json_encode($participant), "stream" => Q::json_encode($stream->toArray()))); // Stream messages to post $messages[$publisherId][$sn] = array('type' => 'Streams/unsubscribe'); $pMessages[] = array('type' => 'Streams/unsubscribed', 'instructions' => array('publisherId' => $publisherId, 'streamName' => $sn)); } Streams_Message::postMessages($asUserId, $messages, true); Streams_Message::postMessages($asUserId, array($asUserId => array('Streams/participating' => $pMessages)), true); return $participants; }
protected static function subscribersDo($latitude, $longitude, $miles, $publisherId = null, $options = array(), $action = null) { $user = Users::loggedInUser(true); $nearby = Places_Nearby::forSubscribers($latitude, $longitude, $miles); if (!$nearby) { return array(); } if (!isset($publisherId)) { $publisherId = Q_Config::expect('Q', 'app'); } if ($transform = Q::ifset($options, 'transform', null)) { $create = Q::ifset($options, 'create', null); $transformed = call_user_func($transform, $nearby, $options); } else { $transformed = array_keys($nearby); $createMethod = $action === 'subscribe' ? array('Places_Nearby', '_create') : null; $create = Q::ifset($options, 'create', $createMethod); } $streams = Streams::fetch(null, $publisherId, $transformed); $participants = Streams_Participant::select('*')->where(array('publisherId' => $publisherId, 'streamName' => $transformed, 'userId' => $user->id))->ignoreCache()->fetchDbRows(null, null, 'streamName'); foreach ($nearby as $name => $info) { $name = isset($transformed[$name]) ? $transformed[$name] : $name; if (empty($streams[$name])) { if (empty($create)) { continue; } $params = compact('publisherId', 'latitude', 'longitude', 'transformed', 'miles', 'nearby', 'name', 'info', 'streams'); $streams[$name] = call_user_func($create, $params, $options); } $stream = $streams[$name]; $subscribed = 'yes' === Q::ifset($participants, $name, 'subscribed', 'no'); if ($action === 'subscribe' and !$subscribed) { $stream->subscribe($options); } else { if ($action === 'unsubscribe' and $subscribed) { $stream->unsubscribe($options); } } } return $streams; }
/** * Fetch a particular participant in the stream, if it exists. * @method getParticipant * @param {string} [$userId=Users::loggedInUser(true)->id] The id of the user who may or may not be participating in the stream * @return {Db_Row|null} */ function getParticipant($userId = null) { if (!$userId) { $userId = Users::loggedInUser(true)->id; } $rows = Streams_Participant::select('*')->where(array('publisherId' => $this->publisherId, 'streamName' => $this->name, 'userId' => $userId))->limit(1)->fetchDbRows(); return $rows ? reset($rows) : null; }