Beispiel #1
0
/**
 * 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();
    }
}
Beispiel #2
0
 /**
  * If the user is subscribed, get the Streams_Subscription object.
  * Otherwise, returns false, or null if the user isn't logged in.
  * @param {string} $ofUserId Defaults to logged-in user's id, if any.
  * @return {Streams_Subscription|false|null}
  */
 function subscription($ofUserId = null)
 {
     if (!isset($ofUserId)) {
         $user = Users::loggedInUser();
         if (!$user) {
             return null;
         }
         $ofUserId = $user->id;
     }
     $s = new Streams_Subscription();
     $s->publisherId = $this->publisherId;
     $s->streamName = $this->name;
     $s->ofUserId = $ofUserId;
     return $s->retrieve();
 }
Beispiel #3
0
 /**
  * Subscribe to one or more streams, to start receiving notifications.
  * Posts "Streams/subscribe" message to the streams.
  * Also posts "Streams/subscribed" messages to user's "Streams/participating" stream.
  *	If options are not given check the subscription templates:
  *	1. generic publisher id and generic user
  *	2. exact publisher id and generic user
  *	3. generic publisher id and exact user
  *	default is to subscribe to ALL messages.
  *	If options are supplied - skip templates and use options.
  * Using subscribe if subscription is already active will modify existing
  * subscription - change type(s) or modify notifications
  * @method subscribe
  * @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 {array} [$options.filter] optional array with two keys
  * @param {array} [$options.filter.types] array of message types, if this is empty then subscribes to all types
  * @param {array} [$options.filter.notifications=0] limit number of notifications, 0 means no limit
  * @param {datetime} [$options.untilTime=null] time limit, if any for subscription
  * @param {array} [$options.rule=array()] optionally override the rule for new subscriptions
  * @param {array} [$options.rule.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 {datetime} [$options.rule.readyTime] time from which user is ready to receive notifications again
  * @param {array} [$options.rule.filter] optionally set a filter for the rules to add
  * @param {boolean} [$options.skipRules] if true, do not attempt to create rules for new subscriptions
  * @param {boolean} [$options.skipAccess] if true, skip access check for whether user can join and subscribe
  * @return {array} An array of Streams_Participant rows from the database.
  */
 static function subscribe($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');
     }
     $participants = Streams::join($asUserId, $publisherId, $streams2, array('subscribed' => true, 'noVisit' => true, 'skipAccess' => Q::ifset($options, 'skipAccess', false)));
     $shouldUpdate = false;
     if (isset($options['filter'])) {
         $filter = Q::json_encode($options['filter']);
         $shouldUpdate = true;
     }
     $db = Streams_Subscription::db();
     if (isset($options['untilTime'])) {
         $untilTime = $db->toDateTime($options['untilTime']);
         $shouldUpdate = true;
     }
     $subscriptions = array();
     $rows = Streams_Subscription::select('*')->where(array('publisherId' => $publisherId, 'streamName' => $streamNames, 'ofUserId' => $asUserId))->fetchAll(PDO::FETCH_ASSOC);
     foreach ($rows as $row) {
         $sn = $row['streamName'];
         $subscriptions[$sn] = $row;
     }
     $messages = array();
     $pMessages = array();
     $streamNamesMissing = array();
     $streamNamesUpdate = array();
     foreach ($streamNames as $sn) {
         $messages[$publisherId][$sn] = array('type' => 'Streams/subscribe');
         $pMessages[] = array('type' => 'Streams/subscribed', 'instructions' => array('publisherId' => $publisherId, 'streamName' => $sn));
         if (empty($subscriptions[$sn])) {
             $streamNamesMissing[] = $sn;
             continue;
         }
         if ($shouldUpdate) {
             $streamNamesUpdate[] = $sn;
         }
     }
     if ($streamNamesUpdate) {
         Streams_Subscription::update()->set(compact('filter', 'untilTime'))->where(array('publisherId' => $publisherId, 'streamName' => $streamNamesUpdate, 'ofUserId' => $asUserId))->execute();
     }
     $rules = array();
     if ($streamNamesMissing) {
         $types = array();
         foreach ($streamNamesMissing as $sn) {
             $stream = $streams2[$sn];
             $types[$stream->type][] = $sn;
         }
         $subscriptionRows = array();
         $ruleRows = array();
         foreach ($types as $type => $sns) {
             // insert subscriptions
             if (!isset($filter) or !isset($untilTime)) {
                 $templates = Streams_Subscription::select('*')->where(array('publisherId' => array('', $publisherId), 'streamName' => $type . '/', 'ofUserId' => array('', $asUserId)))->fetchAll(PDO::FETCH_ASSOC);
                 $template = null;
                 foreach ($templates as $t) {
                     if (!$template or $template['publisherId'] == '' and $t['publisherId'] !== '' or $template['userId'] == '' and $t['userId'] !== '') {
                         $template = $t;
                     }
                 }
             }
             if (!isset($filter)) {
                 $filter = Q::json_encode($template ? Q::json_decode($template['filter']) : Streams_Stream::getConfigField($type, array('subscriptions', 'filter'), array("types" => array("^(?!(Users/)|(Streams/)).*/", "Streams/relatedTo", "Streams/chat/message"), "notifications" => 0)));
             }
             if (!isset($untilTime)) {
                 $untilTime = ($template and $template['duration'] > 0) ? new Db_Expression("CURRENT_TIMESTAMP + INTERVAL {$template['duration']} SECOND") : null;
             }
             foreach ($sns as $sn) {
                 $subscriptions[$sn] = $subscriptionRows[] = new Streams_Subscription(array('publisherId' => $publisherId, 'streamName' => $sn, 'ofUserId' => $asUserId, 'untilTime' => $untilTime, 'filter' => $filter));
             }
             if (!empty($options['skipRules'])) {
                 continue;
             }
             // insert up to one rule per subscription
             $rule = null;
             if (isset($options['rule'])) {
                 $rule = $options['rule'];
                 if (isset($rule['readyTime'])) {
                     $rule['readyTime'] = $db->toDateTime($rule['readyTime']);
                 }
                 if (isset($rule['filter']) and is_array($rule['filter'])) {
                     $rule['filter'] = Q::json_encode($rule['filter']);
                 }
                 if (isset($rule['deliver']) and is_array($rule['deliver'])) {
                     $rule['deliver'] = Q::json_encode($rule['deliver']);
                 }
             }
             if (!isset($rule)) {
                 $templates = Streams_Rule::select('*')->where(array('ofUserId' => array('', $asUserId), 'publisherId' => array('', $publisherId), 'streamName' => $type . '/', 'ordinal' => 1))->fetchAll(PDO::FETCH_ASSOC);
                 foreach ($templates as $t) {
                     if (!$rule or $rule['userId'] == '' and $t['userId'] !== '' or $rule['publisherId'] == '' and $t['publisherId'] !== '') {
                         $rule = $t;
                     }
                 }
             }
             if (!isset($rule)) {
                 $rule = array('deliver' => '{"to": "default"}', 'filter' => '{"types": [], "labels": []}');
             }
             if ($rule) {
                 $rule['ofUserId'] = $asUserId;
                 $rule['publisherId'] = $publisherId;
                 if (empty($rule['readyTime'])) {
                     $rule['readyTime'] = new Db_Expression("CURRENT_TIMESTAMP");
                 }
                 foreach ($sns as $sn) {
                     $row = $rule;
                     $row['streamName'] = $sn;
                     $row['ordinal'] = 1;
                     $row['filter'] = '';
                     $rules[$sn] = $ruleRows[] = $row;
                     $messages[$publisherId][$sn]['instructions'] = Q::json_encode(array('rule' => $row));
                 }
             }
         }
         Streams_Subscription::insertManyAndExecute($subscriptionRows);
         Streams_Rule::insertManyAndExecute($ruleRows);
     }
     foreach ($streamNames as $sn) {
         $subscription = $subscriptions[$sn];
         $stream = $streams2[$sn];
         // 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($subscription), "stream" => Q::json_encode($stream->toArray()), "rule" => isset($rules[$sn]) ? Q::json_encode($rules[$sn]) : null));
     }
     Streams_Message::postMessages($asUserId, $messages, true);
     Streams_Message::postMessages($asUserId, array($asUserId => array('Streams/participating' => $pMessages)), true);
     return $participants;
 }