Пример #1
0
function Streams_participant_response_participant()
{
    if (isset(Streams::$cache['participant'])) {
        return Streams::$cache['participant'];
    }
    $publisherId = Streams::requestedPublisherId(true);
    $streamName = Streams::requestedName(true);
    if (empty($_REQUEST['userId'])) {
        throw new Q_Exception_RequiredField(array('field' => 'userId'));
    }
    $user = Users::loggedInUser();
    $userId = $user ? $user->id : "";
    $stream = Streams::fetch($userId, $publisherId, $streamName);
    if (empty($stream)) {
        throw new Q_Exception_MissingRow(array('table' => 'Stream', 'criteria' => "{publisherId: '{$publisherId}', name: '{$streamName}'}"));
    }
    $stream = reset($stream);
    if (!$stream->testReadLevel('participants')) {
        throw new Users_Exception_NotAuthorized();
    }
    $p = new Streams_Participant();
    $p->publisherId = $publisherId;
    $p->streamName = $streamName;
    $p->userId = $_REQUEST['userId'];
    if ($p->retrieve()) {
        return $p->exportArray();
    }
    return null;
}
function Streams_after_Streams_Stream_save_Streams_greeting($params)
{
    $s = $params['stream'];
    $parts = explode('/', $s->name, 3);
    if (count($parts) < 3) {
        throw new Q_Exception_WrongValue(array('field' => 'stream name', 'range' => 'Streams/greeting/$communityId'));
    }
    $communityId = $parts[2];
    $p = new Streams_Participant();
    $p->publisherId = $communityId;
    $p->streamName = "Streams/community/main";
    $p->userId = $s->publisherId;
    if ($p->retrieve()) {
        $p->setExtra('Streams/greeting', $s->content);
        $p->save();
    }
}
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 "";
        echo "Updated {$i} of {$c} streams";
    }
    echo "\n";
}
Пример #4
0
/**
 * Subscription tool
 * @param array $options
 *  "publisherId" => the id of the user who is publishing the stream
 *  "streamName" => the name of the stream for which to edit access levels
 */
function Streams_subscription_tool($options)
{
    $subscribed = 'no';
    extract($options);
    $user = Users::loggedInUser(true);
    if (!isset($publisherId)) {
        $publisherId = Streams::requestedPublisherId(true);
    }
    if (!isset($streamName)) {
        $streamName = Streams::requestedName();
    }
    $stream = Streams::fetchOne($user->id, $publisherId, $streamName);
    if (!$stream) {
        throw new Q_Exception_MissingRow(array('table' => 'stream', 'criteria' => compact('publisherId', 'streamName')));
    }
    $streams_participant = new Streams_Participant();
    $streams_participant->publisherId = $publisherId;
    $streams_participant->streamName = $streamName;
    $streams_participant->userId = $user->id;
    if ($streams_participant->retrieve()) {
        $subscribed = $streams_participant->subscribed;
    }
    $types = Q_Config::get('Streams', 'types', $stream->type, 'messages', array());
    $messageTypes = array();
    foreach ($types as $type => $msg) {
        $name = Q::ifset($msg, 'title', $type);
        /*
         * group by name
         */
        foreach ($messageTypes as $msgType) {
            if ($msgType['name'] == $name) {
                continue 2;
            }
        }
        $messageTypes[] = array('value' => $type, 'name' => $name);
    }
    $usersFetch = array('userId' => $user->id, 'state' => 'active');
    $devices = array();
    $emails = Users_Email::select('address')->where($usersFetch)->fetchAll(PDO::FETCH_COLUMN);
    $mobiles = Users_Mobile::select('number')->where($usersFetch)->fetchAll(PDO::FETCH_COLUMN);
    foreach ($emails as $email) {
        $devices[] = array('value' => Q::json_encode(array('email' => $email)), 'name' => 'my email');
    }
    foreach ($mobiles as $mobile) {
        $devices[] = array('value' => Q::json_encode(array('mobile' => $mobile)), 'name' => 'my mobile');
    }
    $items = array();
    $rules = Streams_Rule::select('deliver, filter')->where(array('ofUserId' => $user->id, 'publisherId' => $publisherId, 'streamName' => $streamName))->fetchAll(PDO::FETCH_ASSOC);
    while ($rule = array_pop($rules)) {
        $filter = json_decode($rule['filter']);
        /*
         * group by name
         */
        foreach ($rules as $val) {
            if (json_decode($val['filter'])->labels == $filter->labels) {
                continue 2;
            }
        }
        $items[] = array('deliver' => json_decode($rule['deliver']), 'filter' => $filter);
    }
    Q_Response::addScript("plugins/Streams/js/Streams.js");
    Q_Response::addScript("plugins/Streams/js/tools/subscription.js");
    Q_Response::setToolOptions(compact('items', 'subscribed', 'messageTypes', 'devices', 'publisherId', 'streamName'));
}
Пример #5
0
 /**
  * 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');
 }
Пример #6
0
 /**
  * Invites a user (or a future user) to a stream .
  * @method invite
  * @static
  * @param {string} $publisherId The id of the stream publisher
  * @param {string} $streamName The name of the stream the user will be invited to
  * @param {array} $who Array that can contain the following keys:
  * @param {string|array} [$who.userId] user id or an array of user ids
  * @param {string|array} [$who.fb_uid]  fb user id or array of fb user ids
  * @param {string|array} [$who.label]  label or an array of labels, or tab-delimited string
  * @param {string|array} [$who.identifier]  identifier or an array of identifiers, or tab-delimited string
  * @param {integer} [$who.newFutureUsers] the number of new Users_User objects to create via Users::futureUser in order to invite them to this stream. This typically is used in conjunction with passing the "html" option to this function.
  * @param {array} [$options=array()]
  *  @param {string|array} [$options.label] label or an array of labels for adding publisher's contacts
  *  @param {string|array} [$options.myLabel] label or an array of labels for adding logged-in user's contacts
  *  @param {integer} [$options.readLevel] => the read level to grant those who are invited
  *  @param {integer} [$options.writeLevel] => the write level to grant those who are invited
  *  @param {integer} [$options.adminLevel] => the admin level to grant those who are invited
  *	@param {string} [$options.displayName] => the display name to use to represent the inviting user
  *  @param {string} [$options.appUrl] => Can be used to override the URL to which the invited user will be redirected and receive "Q.Streams.token" in the querystring.
  *	@param {array} [$options.html] => an array of ($template, $batchName) such as ("MyApp/foo.handlebars", "foo") for generating html snippets which can then be viewed from and printed via the action Streams/invitations?batchName=$batchName
  * @param {array} [$options.asUserId=null] Invite as this user id
  * @see Users::addLink()
  * @return {array} returns array with keys "success", "invited", "statuses", "identifierTypes", "alreadyParticipating"
  */
 static function invite($publisherId, $streamName, $who, $options = array())
 {
     if (isset($options['asUserId'])) {
         $asUserId = $options['asUserId'];
         $asUser = Users_User::fetch($asUserId);
     } else {
         $asUser = Users::loggedInUser(true);
         $asUserId = $asUser->id;
     }
     // Fetch the stream as the logged-in user
     $stream = Streams::fetch($asUserId, $publisherId, $streamName);
     if (!$stream) {
         throw new Q_Exception_MissingRow(array('table' => 'stream', 'criteria' => 'with that name'), 'streamName');
     }
     $stream = reset($stream);
     // Do we have enough admin rights to invite others to this stream?
     if (!$stream->testAdminLevel('invite') || !$stream->testWriteLevel('join')) {
         throw new Users_Exception_NotAuthorized();
     }
     if (isset($options['html'])) {
         $html = $options['html'];
         if (!is_array($html) or count($html) < 2) {
             throw new Q_Exception_WrongType(array('field' => "options.html", 'type' => 'array of 2 strings'));
         }
         list($template, $batchName) = $html;
         // validate these paths
         $filename = APP_VIEWS_DIR . DS . $template;
         if (!Q::realPath($filename)) {
             throw new Q_Exception_MissingFile(compact('filename'));
         }
         $ext = $pathinfo = pathinfo($template, PATHINFO_EXTENSION);
         if ($ext !== 'handlebars') {
             throw new Q_Exception_WrongValue(array('field' => 'options.html[0]', 'range' => 'a filename with extension .handlebars'));
         }
         $path = Streams::invitationsPath($asUserId) . DS . $batchName;
         Q_Utils::canWriteToPath($path, true, true);
     }
     // get user ids if any to array, throw if user not found
     $raw_userIds = isset($who['userId']) ? Users_User::verifyUserIds($who['userId'], true) : array();
     // merge labels if any
     if (isset($who['label'])) {
         $label = $who['label'];
         if (is_string($label)) {
             $label = array_map('trim', explode("\t", $labels));
         }
         $raw_userIds = array_merge($raw_userIds, Users_User::labelsToIds($asUserId, $label));
     }
     // merge identifiers if any
     $identifierType = null;
     $statuses = null;
     if (isset($who['identifier'])) {
         $identifier = $who['identifier'];
         if (is_string($identifier)) {
             if (Q_Valid::email($who['identifier'])) {
                 $identifierType = 'email';
             } else {
                 if (Q_Valid::phone($who['identifier'])) {
                     $identifierType = 'mobile';
                 }
             }
             $identifier = array_map('trim', explode("\t", $identifier));
         }
         $statuses = array();
         $identifier_ids = Users_User::idsFromIdentifiers($identifier, $statuses);
         $raw_userIds = array_merge($raw_userIds, $identifier_ids);
     }
     // merge fb uids if any
     if (isset($who['fb_uid'])) {
         $fb_uids = $who['fb_uid'];
         if (is_string($fb_uids)) {
             $fb_uids = array_map('trim', explode("\t", $fb_uids));
         }
         $raw_userIds = array_merge($raw_userIds, Users_User::idsFromFacebook($fb_uids));
     }
     if (!empty($who['newFutureUsers'])) {
         $nfu = $who['newFutureUsers'];
         for ($i = 0; $i < $nfu; ++$i) {
             $raw_userIds[] = Users::futureUser('none', null)->id;
         }
     }
     // ensure that each userId is included only once
     // and remove already participating users
     $raw_userIds = array_unique($raw_userIds);
     $total = count($raw_userIds);
     $userIds = Streams_Participant::filter($raw_userIds, $stream);
     $to_invite = count($userIds);
     $appUrl = !empty($options['appUrl']) ? $options['appUrl'] : Q_Request::baseUrl() . '/' . Q_Config::get("Streams", "types", $stream->type, "invite", "url", "plugins/Streams/stream");
     // now check and define levels for invited user
     $readLevel = isset($options['readLevel']) ? $options['readLevel'] : null;
     if (isset($readLevel)) {
         if (!$stream->testReadLevel($readLevel)) {
             // We can't assign greater read level to other people than we have ourselves!
             throw new Users_Exception_NotAuthorized();
         }
     }
     $writeLevel = isset($options['writeLevel']) ? $options['writeLevel'] : null;
     if (isset($writeLevel)) {
         if (!$stream->testWriteLevel($writeLevel)) {
             // We can't assign greater write level to other people than we have ourselves!
             throw new Users_Exception_NotAuthorized();
         }
     }
     $adminLevel = isset($options['adminLevel']) ? $options['adminLevel'] : null;
     if (isset($adminLevel)) {
         if (!$stream->testAdminLevel($adminLevel + 1)) {
             // We can't assign an admin level greater, or equal, to our own!
             // A stream's publisher can assign owners. Owners can assign admins.
             // Admins can confer powers to invite others, to some people.
             // Those people can confer the privilege to publish a message re this stream.
             // But admins can't assign other admins, and even stream owners
             // can't assign other owners.
             throw new Users_Exception_NotAuthorized();
         }
     }
     // calculate expiry time
     $duration = Q_Config::get("Streams", "types", $stream->type, "invite", "duration", false);
     $expiry = $duration ? strtotime($duration) : null;
     // let node handle the rest, and get the result
     $params = array("Q/method" => "Streams/Stream/invite", "invitingUserId" => $asUserId, "username" => $asUser->username, "userIds" => Q::json_encode($userIds), "stream" => Q::json_encode($stream->toArray()), "appUrl" => $appUrl, "label" => Q::ifset($options, 'label', null), "myLabel" => Q::ifset($options, 'myLabel', null), "readLevel" => $readLevel, "writeLevel" => $writeLevel, "adminLevel" => $adminLevel, "displayName" => isset($options['displayName']) ? $options['displayName'] : Streams::displayName($asUser), "expiry" => $expiry);
     if ($template) {
         $params['template'] = $template;
         $params['batchName'] = $batchName;
     }
     $result = Q_Utils::queryInternal('Q/node', $params);
     return array('success' => $result, 'invited' => $userIds, 'statuses' => $statuses, 'identifierType' => $identifierType, 'alreadyParticipating' => $total - $to_invite);
 }
Пример #7
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();
    }
}
Пример #8
0
 /**
  * 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);
 }
Пример #9
0
 /**
  * Assigns unique id to 'token' field if not set
  * Saves corresponding row in Streams_Invited table
  * Inserting a new invite affects corresponding row in Streams_Participant table
  * @method beforeSave
  * @param {array} $modifiedFields
  *	The fields that have been modified
  * @return {array}
  */
 function beforeSave($modifiedFields)
 {
     if (!$this->retrieved) {
         if (!isset($modifiedFields['token'])) {
             $this->token = $modifiedFields['token'] = self::db()->uniqueId(self::table(), 'token', array('length' => Q_Config::get('Streams', 'invites', 'tokens', 'length', 16), 'characters' => Q_Config::get('Streams', 'invites', 'tokens', 'characters', 'abcdefghijklmnopqrstuvwxyz')));
         }
         $p = new Streams_Participant();
         $p->publisherId = $modifiedFields['publisherId'];
         $p->streamName = $modifiedFields['streamName'];
         $p->userId = $modifiedFields['userId'];
         if (!$p->retrieve()) {
             $p->state = 'invited';
             $p->reason = '';
             $p->save();
         }
     }
     if (array_key_exists('state', $modifiedFields) or array_key_exists('expireTime', $modifiedFields)) {
         $invited = new Streams_Invited();
         $invited->userId = $this->userId;
         // shouldn't change
         $invited->token = $this->token;
         // shouldn't change
         if (array_key_exists('state', $modifiedFields)) {
             $invited->state = $modifiedFields['state'];
         }
         if (array_key_exists('expireTime', $modifiedFields)) {
             $invited->expireTime = $modifiedFields['expireTime'];
         }
         $invited->save(true);
     }
     return parent::beforeSave($modifiedFields);
 }
Пример #10
0
 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;
 }
Пример #11
0
 /**
  * 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;
 }