/** * Subscribe to the stream's messages<br/> * If options are not given check the subscription templates: * 1. exact stream name and exact user id * 2. generic stream name and exact user id * 3. exact stream name and generic user * 4. generic stream name and generic user * default is to subscribe to ALL messages. * If options supplied - skip templates and use options<br/><br/> * Using subscribe if subscription is already active will modify existing * subscription - change type(s) or modify notifications * @method subscribe * @param $options=array() {array} * @param {array} [$options.types] array of message types, if this is empty then subscribes to all types * @param {integer} [$options.notifications=0] limit number of notifications, 0 means no limit * @param {datetime} [$options.untilTime=null] time limit, if any for subscription * @param {datetime} [$options.readyTime] time from which user is ready to receive notifications again * @param {string} [$options.userId] the user subscribing to the stream. Defaults to the logged in user. * @param {array} [$options.deliver=array('to'=>'default')] under "to" key, named the field under Streams/rules/deliver config, which will contain the names of destinations, which can include "email", "mobile", "email+pending", "mobile+pending" * @param {boolean} [$options.skipRules] if true, do not attempt to create rules * @param {boolean} [$options.skipAccess] if true, skip access check for whether user can subscribe * @return {Streams_Subscription|false} */ function subscribe($options = array()) { $stream = $this->fetchAsUser($options, $userId, $user); if (empty($options['skipAccess']) and !$stream->testReadLevel('messages')) { if (!$stream->testReadLevel('see')) { throw new Streams_Exception_NoSuchStream(); } throw new Users_Exception_NotAuthorized(); } // first make user a participant $stream->join(array("userId" => $userId, "subscribed" => true, "noVisit" => true, "skipAccess" => Q::ifset($options, 'skipAccess', false))); // check for 'messages' level $s = new Streams_Subscription(); $s->publisherId = $stream->publisherId; $s->streamName = $stream->name; $s->ofUserId = $userId; $s->retrieve(); $type = null; if ($template = $stream->getSubscriptionTemplate('Streams_Subscription', $userId, $type)) { $filter = json_decode($template->filter, true); } else { $filter = array('types' => array(), 'notifications' => 0); } if (isset($options['types'])) { $filter['types'] = !empty($options['types']) ? $options['types'] : $filter['types']; } if (isset($options['notifications'])) { $filter['notifications'] = $options['notifications']; } $s->filter = Q::json_encode($filter); if (isset($options['untilTime'])) { $s->untilTime = $options['untilTime']; } else { if ($type > 0 and $template and $template->duration > 0) { $s->untilTime = date("c", time() + $template->duration); } } if (!$s->save(true)) { return false; } if (empty($options['skipRules'])) { // Now let's handle rules $type2 = null; $template = $stream->getSubscriptionTemplate('Streams_Rule', $userId, $type2); $ruleSuccess = true; if ($type2 !== 0) { $rule = new Streams_Rule(); $rule->ofUserId = $userId; $rule->publisherId = $stream->publisherId; $rule->streamName = $stream->name; if (empty($template) and $rule->retrieve()) { $ruleSuccess = false; } else { $rule->readyTime = isset($options['readyTime']) ? $options['readyTime'] : new Db_Expression('CURRENT_TIMESTAMP'); $rule->filter = !empty($template->filter) ? $template->filter : '{"types":[],"labels":[]}'; $rule->relevance = !empty($template->relevance) ? $template->relevance : 1; $rule->deliver = !empty($template->deliver) ? $template->deliver : Q::json_encode(Q::ifset($options, 'deliver', array('to' => 'default'))); $ruleSuccess = !!$rule->save(); } } } // skip error testing for rule save BUT inform node. // Node can notify user to check the rules Q_Utils::sendToNode(array("Q/method" => "Streams/Stream/subscribe", "subscription" => Q::json_encode($s->toArray()), "stream" => Q::json_encode($stream->toArray()), "success" => Q::json_encode($ruleSuccess))); // Post Streams/subscribe message to the stream $stream->post($userId, array('type' => 'Streams/subscribe'), true); // Now post Streams/subscribed message to Streams/participating Streams_Message::post($userId, $userId, 'Streams/participating', array('type' => 'Streams/subscribed', 'instructions' => Q::json_encode(array('publisherId' => $stream->publisherId, 'streamName' => $stream->name))), true); return $s; }
/** * Create or update subscription */ function Streams_subscription_put($params) { $items = array(); $subscribed = 'no'; $updateTemplate = true; $streamName = Streams::requestedName(); $publisherId = Streams::requestedPublisherId(true); $user = Users::loggedInUser(true); extract($_REQUEST); $items = json_decode($items, true); $stream = Streams::fetchOne($user->id, $publisherId, $streamName); if (!$stream) { throw new Q_Exception_MissingRow(array('table' => 'stream', 'criteria' => compact('publisherId', 'streamName'))); } $rules = Streams_Rule::select('*')->where(array('ofUserId' => $user->id, 'publisherId' => $publisherId, 'streamName' => $streamName))->fetchDbRows(null, '', 'ordinal'); $types = Q_Config::get('Streams', 'types', $stream->type, 'messages', array()); if ($subscribed !== 'no') { // update rules while ($item = array_pop($items)) { // join "grouped" message types to $items foreach ($types as $type => $msg) { if ($msg['title'] == $item['filter']->labels and $type != $item['filter']->types) { $items[] = (object) array('deliver' => $item->deliver, 'filter' => array('types' => $type, 'labels' => $msg['title'], 'notifications' => $item['filter']->notifications)); } } if (!($rule = array_pop($rules))) { $rule = new Streams_Rule(); $rule->ofUserId = $user->id; $rule->publisherId = $publisherId; $rule->streamName = $streamName; $rule->relevance = 1; } $rule->filter = Q::json_encode($item['filter']); $rule->deliver = Q::json_encode($item['deliver']); $rule->save(); } } foreach ($rules as $rule) { $rule->remove(); } $streams_subscription = new Streams_Subscription(); $streams_subscription->streamName = $streamName; $streams_subscription->publisherId = $publisherId; $streams_subscription->ofUserId = $user->id; $streams_subscription->filter = Q::json_encode(array()); $streams_subscription->retrieve(); $streams_participant = new Streams_Participant(); $streams_participant->publisherId = $publisherId; $streams_participant->streamName = $streamName; $streams_participant->userId = $user->id; $streams_participant->state = 'participating'; $streams_participant->reason = ''; $streams_participant->retrieve(); $streams_participant->subscribed = $subscribed; $streams_participant->save(); if ($subscribed === 'yes') { $stream->subscribe(array('skipRules' => true)); } else { $stream->unsubscribe(); } }