Пример #1
0
function Streams_message_response_messages()
{
    if (isset(Streams::$cache['message'])) {
        $message = Streams::$cache['message'];
        return Db::exportArray(array($message->ordinal => $message));
    }
    if (isset(Streams::$cache['messages'])) {
        return Db::exportArray(Streams::$cache['messages']);
    }
    $publisherId = Streams::requestedPublisherId(true);
    $streamName = Streams::requestedName(true);
    $type = Streams::requestedMessageType();
    $stream = Q::ifset(Streams::$cache, 'stream', Streams::fetchOne(null, $publisherId, $streamName, true));
    $maxLimit = Streams_Stream::getConfigField($type, 'getMessagesLimit', 100);
    $limit = min($maxLimit, Q::ifset($_REQUEST, 'limit', $maxLimit));
    if (isset($_REQUEST['ordinal'])) {
        $min = $_REQUEST['ordinal'];
        $limit = 1;
    }
    if (isset($_REQUEST['min'])) {
        $min = $_REQUEST['min'];
    }
    $max = isset($_REQUEST['max']) ? $_REQUEST['max'] : -1;
    if (isset($_REQUEST['ascending'])) {
        $ascending = $_REQUEST['ascending'];
    }
    if (!$stream->testReadLevel('messages')) {
        throw new Users_Exception_NotAuthorized();
    }
    $messages = $stream->getMessages(compact('type', 'min', 'max', 'limit', 'ascending'));
    return Db::exportArray($messages);
}
Пример #2
0
function Streams_after_Q_responseExtras()
{
    if ($preloaded = Streams_Stream::$preloaded) {
        $preloaded = Db::exportArray($preloaded);
        Q_Response::setScriptData('Q.plugins.Streams.Stream.preloaded', $preloaded);
    }
}
Пример #3
0
function Users_after_Q_responseExtras()
{
    if ($preloaded = Users_User::$preloaded) {
        Q_Response::setScriptData('Q.plugins.Users.User.preloaded', Db::exportArray($preloaded, array('asAvatar' => true)));
    }
    Q_Response::setScriptData('Q.plugins.Users.roles', Users::roles());
}
Пример #4
0
function Streams_after_Q_objects()
{
    $user = Users::loggedInUser();
    if (!$user) {
        return;
    }
    $invite = Streams::$followedInvite;
    if (!$invite) {
        return;
    }
    $displayName = $user->displayName();
    if ($displayName) {
        return;
    }
    $stream = new Streams_Stream();
    $stream->publisherId = $invite->publisherId;
    $stream->name = $invite->streamName;
    if (!$stream->retrieve()) {
        throw new Q_Exception_MissingRow(array('table' => 'stream', 'criteria' => 'with that name'), 'streamName');
    }
    // Prepare the complete invite dialog
    $invitingUser = Users_User::fetch($invite->invitingUserId);
    list($relations, $related) = Streams::related($user->id, $stream->publisherId, $stream->name, false);
    $params = array('displayName' => null, 'action' => 'Streams/basic', 'icon' => $user->iconUrl(), 'token' => $invite->token, 'user' => array('icon' => $invitingUser->iconUrl(), 'displayName' => $invitingUser->displayName(array('fullAccess' => true))), 'stream' => $stream->exportArray(), 'relations' => Db::exportArray($relations), 'related' => Db::exportArray($related));
    $config = Streams_Stream::getConfigField($stream->type, 'invite', array());
    $defaults = Q::ifset($config, 'dialog', array());
    $tree = new Q_Tree($defaults);
    if ($tree->merge($params)) {
        $dialogData = $tree->getAll();
        if ($dialogData) {
            Q_Response::setScriptData('Q.plugins.Streams.invite.dialog', $dialogData);
            Q_Response::addTemplate('Streams/invite/complete');
        }
    }
}
function Streams_after_Users_Contact_removeExecute($params)
{
    // Update avatar as viewed by everyone who was in that contacts list
    $contacts = Streams::$cache['contacts_removed'];
    foreach ($contacts as $contact) {
        Streams::updateAvatar($contact->contactUserId, $contact->userId);
    }
    Streams_Message::post(null, $contact->userId, 'Streams/contacts', array('type' => 'Streams/contacts/removed', 'instructions' => array('contacts' => Db::exportArray($contacts))), true);
}
Пример #6
0
function Users_after_Q_responseExtras()
{
    if ($preloaded = Users_User::$preloaded) {
        Q_Response::setScriptData('Q.plugins.Users.User.preloaded', Db::exportArray($preloaded, array('asAvatar' => true)));
    }
    Q_Response::setScriptData('Q.plugins.Users.roles', Users::roles());
    $user = Users::loggedInUser();
    Q_Response::addHtmlCssClass($user ? 'Users_loggedIn' : 'Users_loggedOut');
}
Пример #7
0
/**
 * Adds contacts to the system. Fills the "contacts" slot.
 * @param {array} $_REQUEST
 * @param {string} $_REQUEST.label The label of the contact
 * @param {string} $_REQUEST.contactUserId The contactUserId of the contact
 * @param {string} [$_REQUEST.nickname] The nickname of the contact
 * @param {string} [$_REQUEST.userId=Users::loggedInUser(true)->id] You can override the user id, if another plugin adds a hook that allows you to do this
 */
function Users_contact_post($params = array())
{
    $req = array_merge($_REQUEST, $params);
    Q_Request::requireFields(array('label', 'contactUserId'), $req, true);
    $loggedInUserId = Users::loggedInUser(true)->id;
    $userId = Q::ifset($req, 'userId', $loggedInUserId);
    $contactUserId = $req['contactUserId'];
    $nickname = Q::ifset($req, 'nickname', null);
    $contacts = Users_Contact::addContact($userId, $req['label'], $contactUserId, $nickname);
    Q_Response::setSlot('contacts', Db::exportArray($contacts));
}
Пример #8
0
function Users_user_response_users($params = array())
{
    $req = array_merge($_REQUEST, $params);
    Q_Valid::requireFields(array('userIds'), $req, true);
    $userIds = $req['userIds'];
    if (is_string($userIds)) {
        $userIds = explode(",", $userIds);
    }
    $fields = Q_Config::expect('Users', 'avatarFields');
    $users = Users_User::select($fields)->where(array('id' => $userIds))->fetchDbRows(null, null, 'id');
    return Q_Response::setSlot('users', Db::exportArray($users, array('asAvatar' => true)));
}
Пример #9
0
function Streams_stream_response_streams()
{
    // happens only during non-GET requests
    $publisherId = Streams::requestedPublisherId(true);
    $name = Streams::requestedName(true);
    $fields = Streams::requestedFields();
    $limit = isset($_REQUEST['limit']) ? $_REQUEST['limit'] : null;
    $user = Users::loggedInUser();
    $userId = $user ? $user->id : "";
    $streams = Streams::fetch($userId, $publisherId, $name, $fields ? $fields : '*', $limit ? compact('limit') : array());
    return Streams::$cache['streams'] = Db::exportArray($streams);
}
Пример #10
0
function Streams_stream_response_streams()
{
    // happens only during non-GET requests
    $publisherId = Streams::requestedPublisherId(true);
    $name = Streams::requestedName(true);
    $fields = Streams::requestedFields();
    $limit = isset($_REQUEST['limit']) ? $_REQUEST['limit'] : null;
    $user = Users::loggedInUser();
    $userId = $user ? $user->id : "";
    $options = array('withParticipant' => true);
    if (isset($limit)) {
        $options['limit'] = $limit;
    }
    $streams = Streams::fetch($userId, $publisherId, $name, $fields ? $fields : '*', $options);
    return Streams::$cache['streams'] = Db::exportArray($streams);
}
Пример #11
0
function Streams_avatar_response()
{
    $prefix = $limit = $userIds = $batch = $public = null;
    extract($_REQUEST, EXTR_IF_EXISTS);
    $user = Users::loggedInUser();
    $asUserId = $user ? $user->id : "";
    if (isset($prefix)) {
        $avatars = Streams_Avatar::fetchByPrefix($asUserId, $prefix, compact('limit', 'public'));
    } else {
        if (isset($batch)) {
            $batch = json_decode($batch, true);
            if (!isset($batch)) {
                throw new Q_Exception_WrongValue(array('field' => 'batch', 'range' => '{userIds: [userId1, userId2, ...]}'));
            }
            if (!isset($batch['userIds'])) {
                throw new Q_Exception_RequiredField(array('field' => 'userIds'));
            }
            $userIds = $batch['userIds'];
        }
        if (!isset($userIds)) {
            throw new Q_Exception_RequiredField(array('field' => 'userIds'));
        }
        if (is_string($userIds)) {
            $userIds = explode(",", $userIds);
        }
        $avatars = Streams_Avatar::fetch($asUserId, $userIds);
    }
    $avatars = Db::exportArray($avatars);
    if (isset($batch)) {
        $result = array();
        foreach ($userIds as $userId) {
            $result[] = array('slots' => array('avatar' => isset($avatars[$userId]) ? $avatars[$userId] : null));
        }
        Q_Response::setSlot('batch', $result);
    } else {
        Q_Response::setSlot('avatars', $avatars);
    }
    return $avatars;
}
Пример #12
0
/**
 * Adds contacts to the system. Fills the "contacts" slot.
 * @param {array} $_REQUEST
 * @param {string} $_REQUEST.label The label of the contact
 * @param {string} $_REQUEST.contactUserId The contactUserId of the contact
 * @param {string} [$_REQUEST.nickname] The nickname of the contact
 * @param {string} [$_REQUEST.userId=Users::loggedInUser(true)->id] You can override the user id, if another plugin adds a hook that allows you to do this
 */
function Users_contact_post($params = array())
{
    $req = array_merge($_REQUEST, $params);
    Q_Request::requireFields(array('label', 'contactUserId'), $req, true);
    $loggedInUserId = Users::loggedInUser(true)->id;
    $userId = Q::ifset($req, 'userId', $loggedInUserId);
    $contactUserId = $req['contactUserId'];
    $nickname = Q::ifset($req, 'nickname', null);
    $l = $req['label'];
    if ($userId !== $loggedInUserId) {
        Users_User::fetch($userId, true);
    }
    Users_User::fetch($contactUserId, true);
    Users::canManageContacts($loggedInUserId, $userId, $l, true);
    $label = new Users_Label();
    $label->userId = $userId;
    $label->label = $l;
    if (!$label->retrieve()) {
        throw new Q_Exception_MissingRow(array('table' => 'Users_Label', 'criteria' => json_encode($label->fields)));
    }
    $contacts = Users_Contact::addContact($userId, $l, $contactUserId, $nickname);
    Q_Response::setSlot('contacts', Db::exportArray($contacts));
}
Пример #13
0
function Streams_participant_response_participants()
{
    if (isset(Streams::$cache['participant'])) {
        $participant = Streams::$cache['participant'];
        return Db::exportArray(array($participant->userId => $participant));
    }
    $publisherId = Streams::requestedPublisherId(true);
    $streamName = Streams::requestedName(true);
    $limit = isset($_REQUEST['limit']) ? $_REQUEST['limit'] : 10;
    $offset = isset($_REQUEST['offset']) ? $_REQUEST['offset'] : -1;
    $state = isset($_REQUEST['state']) ? $_REQUEST['state'] : null;
    $user = Users::loggedInUser();
    $userId = $user ? $user->id : "";
    $stream = Streams::fetchOne($userId, $publisherId, $streamName);
    if (empty($stream)) {
        throw new Q_Exception_MissingRow(array('table' => 'Stream', 'criteria' => "{publisherId: '{$publisherId}', name: '{$streamName}'}"));
    }
    if (!$stream->testReadLevel('participants')) {
        throw new Users_Exception_NotAuthorized();
    }
    $participants = $stream->getParticipants(compact('limit', 'offset', 'state'));
    Db::exportArray($participants);
}
Пример #14
0
function Users_avatar_response($params)
{
    $userIds = $batch = null;
    extract($_REQUEST, EXTR_IF_EXISTS);
    if ($batch) {
        $batch = json_decode($batch, true);
        if (!isset($batch)) {
            throw new Q_Exception_WrongValue(array('field' => 'batch', 'range' => '{userIds: [userId1, userId2, ...]}'));
        }
        if (!isset($batch['userIds'])) {
            throw new Q_Exception_RequiredField(array('field' => 'userIds'));
        }
        $userIds = $batch['userIds'];
    } else {
        if (!isset($userIds)) {
            throw new Q_Exception_RequiredField(array('field' => 'userIds'), 'userIds');
        }
    }
    if (is_string($userIds)) {
        $userIds = explode(",", $userIds);
    }
    $fields = Q_Config::expect('Users', 'avatarFields');
    $users = Users_User::select($fields)->where(array('id' => $userIds))->fetchDbRows(null, null, 'id');
    $avatars = Db::exportArray($users);
    if (!isset($batch)) {
        Q_Response::setSlot('avatars', $avatars);
        return $avatars;
    }
    if ($batch) {
        $result = array();
        foreach ($userIds as $userId) {
            $result[] = array('slots' => array('avatar' => isset($avatars[$userId]) ? $avatars[$userId] : null));
        }
        Q_Response::setSlot('batch', $result);
    }
    return $avatars;
}
Пример #15
0
function Streams_message_response_messages()
{
    if (isset(Streams::$cache['message'])) {
        $message = Streams::$cache['message'];
        return Db::exportArray(array($message->ordinal => $message));
    }
    if (isset(Streams::$cache['messages'])) {
        return Db::exportArray(Streams::$cache['messages']);
    }
    $publisherId = Streams::requestedPublisherId(true);
    $streamName = Streams::requestedName(true);
    $type = Streams::requestedMessageType();
    $maxLimit = Q_Config::get('Streams', 'defaults', 'getMessagesLimit', 100);
    $limit = min($maxLimit, Q::ifset($_REQUEST, 'limit', $maxLimit));
    if (isset($_REQUEST['ordinal'])) {
        $min = $_REQUEST['ordinal'];
        $limit = 1;
    }
    if (isset($_REQUEST['min'])) {
        $min = $_REQUEST['min'];
    }
    $max = isset($_REQUEST['max']) ? $_REQUEST['max'] : -1;
    if (isset($_REQUEST['ascending'])) {
        $ascending = $_REQUEST['ascending'];
    }
    $user = Users::loggedInUser();
    $userId = $user ? $user->id : "";
    $stream = isset(Streams::$cache['stream']) ? Streams::$cache['stream'] : Streams::fetchOne($userId, $publisherId, $streamName);
    if (!$stream) {
        throw new Q_Exception_MissingRow(array('table' => 'Stream', 'criteria' => "{publisherId: '{$publisherId}', name: '{$streamName}'}"));
    }
    if (!$stream->testReadLevel('messages')) {
        throw new Users_Exception_NotAuthorized();
    }
    $messages = $stream->getMessages(compact('type', 'min', 'max', 'limit', 'ascending'));
    return Db::exportArray($messages);
}
Пример #16
0
function Streams_form_post($params = array())
{
    if (empty($_REQUEST['inputs'])) {
        throw new Q_Exception_RequiredField(array('field' => 'inputs'));
    }
    $inputs = Q::json_decode($_REQUEST['inputs'], true);
    $user = Users::loggedInUser(true);
    $r = array_merge($_REQUEST, $params);
    $streams = array();
    foreach ($inputs as $name => $info) {
        $inputName = "input_{$name}";
        if (!isset($r[$inputName])) {
            continue;
        }
        if (!is_array($info) or count($info) < 4) {
            throw new Q_Exception_WrongValue(array('field' => 'inputs', 'range' => 'array of name => (streamExists, publisherId, streamName, fieldName)'));
        }
        list($streamExists, $publisherId, $streamName, $fieldName) = $info;
        $stream = Streams::fetchOne(null, $publisherId, $streamName);
        if (!$stream) {
            if ($user->id !== $publisherId or !Q_Config::get('Streams', 'possibleUserStreams', $streamName, false)) {
                throw new Users_Exception_NotAuthorized();
            }
            $stream = Streams::create(null, $publisherId, null, array('name' => $streamName));
        }
        $attribute = substr($fieldName, 0, 10) === 'attribute:' ? substr($fieldName, 10) : null;
        if ($attribute) {
            $stream->setAttribute($attribute, $r[$inputName]);
        } else {
            $stream->{$fieldName} = $r[$inputName];
        }
        $stream->save();
        $streams[$stream->name] = $stream;
    }
    Q_Response::setSlot('streams', Db::exportArray($streams));
}
Пример #17
0
function Streams_related_response()
{
    if (!Q_Request::slotName('relations') and !Q_Request::slotName('streams')) {
        return;
    }
    $user = Users::loggedInUser();
    $asUserId = $user ? $user->id : '';
    $publisherId = Streams::requestedPublisherId(true);
    $streamName = Streams::requestedName(true, 'original');
    $isCategory = !empty($_REQUEST['isCategory']);
    $slotNames = Q_Request::slotNames();
    $streams_requested = in_array('relatedStreams', $slotNames);
    $options = array('relationsOnly' => !$streams_requested, 'orderBy' => !empty($_REQUEST['ascending']));
    if (isset($_REQUEST['limit'])) {
        $options['limit'] = $_REQUEST['limit'];
    }
    if (isset($_REQUEST['offset'])) {
        $options['offset'] = $_REQUEST['offset'];
    }
    if (isset($_REQUEST['min'])) {
        $options['min'] = $_REQUEST['min'];
    }
    if (isset($_REQUEST['max'])) {
        $options['max'] = $_REQUEST['max'];
    }
    if (isset($_REQUEST['type'])) {
        $options['type'] = $_REQUEST['type'];
    }
    if (isset($_REQUEST['prefix'])) {
        $options['prefix'] = $_REQUEST['prefix'];
    }
    $result = Streams::related($asUserId, $publisherId, $streamName, $isCategory, $options);
    if ($streams_requested) {
        $rel = Db::exportArray($result[0], array('numeric' => true));
    } else {
        $rel = Db::exportArray($result, array('numeric' => true));
    }
    if (!empty($_REQUEST['omitRedundantInfo'])) {
        if ($isCategory) {
            foreach ($rel as &$r) {
                unset($r['toPublisherId']);
                unset($r['toStreamName']);
            }
        } else {
            foreach ($rel as &$r) {
                unset($r['fromPublisherId']);
                unset($r['fromStreamName']);
            }
        }
    }
    Q_Response::setSlot('relations', $rel);
    if (!$streams_requested) {
        return;
    }
    $streams = $result[1];
    $arr = Db::exportArray($streams, array('numeric' => true));
    foreach ($arr as $k => $stream) {
        if (!$stream) {
            continue;
        }
        $s = $streams[$stream['name']];
        $arr[$k]['access'] = array('readLevel' => $s->get('readLevel', $s->readLevel), 'writeLevel' => $s->get('writeLevel', $s->writeLevel), 'adminLevel' => $s->get('adminLevel', $s->adminLevel));
    }
    Q_Response::setSlot('relatedStreams', $arr);
    $stream = $result[2];
    if (is_array($stream)) {
        Q_Response::setSlot('streams', Db::exportArray($stream));
        return;
    } else {
        if (is_object($stream)) {
            Q_Response::setSlot('stream', $stream->exportArray());
        } else {
            Q_Response::setSlot('stream', false);
        }
    }
    if (!empty($_REQUEST['messages'])) {
        $max = -1;
        $limit = $_REQUEST['messages'];
        $messages = false;
        $type = isset($_REQUEST['messageType']) ? $_REQUEST['messageType'] : null;
        if ($stream->testReadLevel('messages')) {
            $messages = Db::exportArray($stream->getMessages(compact('type', 'max', 'limit')));
        }
        Q_Response::setSlot('messages', $messages);
    }
    if (!empty($_REQUEST['participants'])) {
        $limit = $_REQUEST['participants'];
        $offset = -1;
        $participants = false;
        if ($stream->testReadLevel('participants')) {
            $participants = Db::exportArray($stream->getParticipants(compact('limit', 'offset')));
        }
        Q_Response::setSlot('participants', $participants);
    }
}
Пример #18
0
/**
 * Used to get a stream
 *
 * @param {array} $_REQUEST 
 * @param {string} $_REQUEST.publisherId Required
 * @param {string} $_REQUEST.streamName Required streamName or name
 * @param {integer} [$_REQUEST.messages] optionally pass a number here to fetch latest messages
 * @param {integer} [$_REQUEST.participants] optionally pass a number here to fetch participants
 * @return {void}
 */
function Streams_stream_response()
{
    // this handler is only for GET requests
    if (Q_Request::method() !== 'GET') {
        return null;
    }
    $publisherId = Streams::requestedPublisherId(true);
    $name = Streams::requestedName(true);
    $fields = Streams::requestedFields();
    $user = Users::loggedInUser();
    $userId = $user ? $user->id : "";
    if (isset(Streams::$cache['stream'])) {
        $stream = Streams::$cache['stream'];
    } else {
        $streams = Streams::fetch($userId, $publisherId, $name, $fields ? $fields : '*', array('withParticipant' => true));
        if (Q_Request::slotName('streams')) {
            Q_Response::setSlot('streams', Db::exportArray($streams));
        }
        if (empty($streams)) {
            if (Q_Request::slotName('stream')) {
                Q_Response::setSlot('stream', null);
                Q_Response::setSlot('messages', null);
                Q_Response::setSlot('participants', null);
                Q_Response::setSlot('related', null);
                Q_Response::setSlot('relatedTo', null);
            } else {
                if (!Q_Request::slotName('streams')) {
                    $app = Q_Config::expect('Q', 'app');
                    Q_Dispatcher::forward("{$app}/notFound");
                }
            }
            return null;
        }
        // The rest of the data is joined only on the first stream
        Streams::$cache['stream'] = $stream = reset($streams);
    }
    if (empty($stream)) {
        if (Q_Request::slotName('stream')) {
            Q_Response::setSlot('stream', null);
        }
        return null;
    }
    if ($userId && !empty($_REQUEST['join'])) {
        $stream->join();
        // NOTE: one of the rare times we may change state in a response handler
    }
    if (Q_Request::slotName('stream')) {
        Q_Response::setSlot('stream', $stream->exportArray());
    }
    if (!empty($_REQUEST['messages'])) {
        $max = -1;
        $limit = $_REQUEST['messages'];
        $messages = false;
        $type = isset($_REQUEST['messageType']) ? $_REQUEST['messageType'] : null;
        if ($stream->testReadLevel('messages')) {
            $messages = Db::exportArray($stream->getMessages(compact('type', 'max', 'limit')));
        }
        Q_Response::setSlot('messages', $messages);
    }
    if (!empty($_REQUEST['participants'])) {
        $limit = $_REQUEST['participants'];
        $participants = false;
        if ($stream->testReadLevel('participants')) {
            $participants = Db::exportArray($stream->getParticipants(compact('limit', 'offset')));
        }
        Q_Response::setSlot('participants', $participants);
    }
}
Пример #19
0
/**
 * Used by HTTP clients to look up streams published by a certain publisher, based on their title
 * @class HTTP Streams lookup
 * @method get
 * @param {array} [$_REQUEST] Parameters that can come from the request
 *   @param {string} $_REQUEST.publisherId  Required. The user id of the publisher of the streams
 *   @param {string|array} $_REQUEST.types  Required. The type (or types) of the streams to find
 *   @param {string|array} $_REQUEST.title  Required. The string to use with SQL's "LIKE" statement. May be rejected depending on configuration.
 */
function Streams_lookup_response_results()
{
    Q_Request::requireFields(array('publisherId', 'types', 'title'), true);
    $streams = Streams::lookup($_REQUEST['publisherId'], $_REQUEST['types'], $_REQUEST['title']);
    return Db::exportArray($streams);
}
Пример #20
0
 /**
  * Post (potentially) multiple messages to multiple streams.
  * @method postMessages
  * @static
  * @param {string} $asUserId
  *  The user to post the message as
  * @param {string} $messages
  *  Array indexed as follows:
  *  array($publisherId => array($streamName => $message))
  *  where $message are either Streams_Message objects, 
  *  or arrays containing all the fields of messages that will need to be posted.
  * @param {booleam} $skipAccess=false
  *  If true, skips the access checks and just posts the message.
  * @return {array}
  *  Returns an array(array(Streams_Message), array(Streams_Stream))
  */
 static function postMessages($asUserId, $messages, $skipAccess = false)
 {
     if (!isset($asUserId)) {
         $asUserId = Users::loggedInUser();
         if (!$asUserId) {
             $asUserId = "";
         }
     }
     if ($asUserId instanceof Users_User) {
         $asUserId = $asUserId->id;
     }
     // Build arrays we will need
     foreach ($messages as $publisherId => $arr) {
         if (!is_array($arr)) {
             throw new Q_Exception_WrongType(array('field' => "messages", 'type' => 'array of publisherId => streamName => message'));
         }
         foreach ($arr as $streamName => &$message) {
             if (!is_array($message)) {
                 if (!$message instanceof Streams_Message) {
                     throw new Q_Exception_WrongType(array('field' => "message under {$publisherId} => {$streamName}", 'type' => 'array or Streams_Message'));
                 }
                 $message = $message->fields;
             }
         }
     }
     // Check if there are any messages to post
     $atLeastOne = false;
     foreach ($messages as $publisherId => $arr) {
         foreach ($arr as $streamName => $m) {
             if (!$m) {
                 continue;
             }
             $atLeastOne = true;
             break 2;
         }
     }
     if (!$atLeastOne) {
         return array(array(), array());
     }
     // Start posting messages, publisher by publisher
     $eventParams = array();
     $posted = array();
     $streams = array();
     $messages2 = array();
     $totals2 = array();
     $updates = array();
     $clientId = Q_Request::special('clientId', '');
     $sendToNode = true;
     foreach ($messages as $publisherId => $arr) {
         $streamNames = array_keys($messages[$publisherId]);
         $streams[$publisherId] = $fetched = Streams::fetch($asUserId, $publisherId, $streamNames, '*', array('refetch' => true, 'begin' => true));
         foreach ($arr as $streamName => $m) {
             // Get the Streams_Stream object
             if (!isset($fetched[$streamName])) {
                 $p = new Q_Exception_MissingRow(array('table' => 'stream', 'criteria' => "publisherId {$publisherId} and name {$streamName}"));
                 $updates[$publisherId]['missingRow'][] = $streamName;
                 continue;
             }
             $p =& $posted[$publisherId][$streamName];
             $p = array();
             if (!$m) {
                 $updates[$publisherId]['noMessages'][] = $streamName;
                 continue;
             }
             $messages3 = is_array($m) && !Q::isAssociative($m) ? $m : array($m);
             $count = count($messages3);
             $updates[$publisherId][$count][] = $streamName;
             $i = 0;
             foreach ($messages3 as $message) {
                 ++$i;
                 $type = isset($message['type']) ? $message['type'] : 'text/small';
                 $content = isset($message['content']) ? $message['content'] : '';
                 $instructions = isset($message['instructions']) ? $message['instructions'] : '';
                 $weight = isset($message['weight']) ? $message['weight'] : 1;
                 if (!isset($message['byClientId'])) {
                     $message['byClientId'] = $clientId ? substr($clientId, 0, 255) : '';
                 }
                 if (is_array($instructions)) {
                     $instructions = Q::json_encode($instructions);
                 }
                 $byClientId = $message['byClientId'];
                 $stream = $fetched[$streamName];
                 // Make a Streams_Message object
                 $message = new Streams_Message();
                 $message->publisherId = $publisherId;
                 $message->streamName = $streamName;
                 $message->insertedTime = new Db_Expression("CURRENT_TIMESTAMP");
                 $message->sentTime = new Db_Expression("CURRENT_TIMESTAMP");
                 $message->byUserId = $asUserId;
                 $message->byClientId = $byClientId ? substr($byClientId, 0, 31) : '';
                 $message->type = $type;
                 $message->content = $content;
                 $message->instructions = $instructions;
                 $message->weight = $weight;
                 $message->ordinal = $stream->messageCount + $i;
                 // thanks to transaction
                 // Set up some parameters for the event hooks
                 $params = $eventParams[$publisherId][$streamName][] = array('publisherId' => $publisherId, 'message' => $message, 'skipAccess' => $skipAccess, 'sendToNode' => &$sendToNode, 'stream' => $stream);
                 /**
                  * @event Streams/post/$streamType {before}
                  * @param {string} publisherId
                  * @param {Streams_Stream} stream
                  * @param {string} message
                  * @return {false} To cancel further processing
                  */
                 if (Q::event("Streams/post/{$stream->type}", $params, 'before') === false) {
                     $results[$stream->name] = false;
                     continue;
                 }
                 /**
                  * @event Streams/message/$messageType {before}
                  * @param {string} publisherId
                  * @param {Streams_Stream} stream
                  * @param {string} message
                  * @return {false} To cancel further processing
                  */
                 if (Q::event("Streams/message/{$type}", $params, 'before') === false) {
                     $results[$stream->name] = false;
                     continue;
                 }
                 if (!$skipAccess && !$stream->testWriteLevel('post')) {
                     $p[] = new Users_Exception_NotAuthorized();
                     /**
                      * @event Streams/notAuthorized {before}
                      * @param {string} publisherId
                      * @param {Streams_Stream} stream
                      * @param {string} message
                      */
                     Q::event("Streams/notAuthorized", $params, 'after');
                     continue;
                 }
                 // if we are still here, mark the message as "in the database"
                 $message->wasRetrieved(true);
                 $p[] = $message;
                 // build the arrays of rows to insert
                 $messages2[] = $mf = $message->fields;
             }
             $totals2[$count][] = array('publisherId' => $mf['publisherId'], 'streamName' => $mf['streamName'], 'messageType' => $mf['type'], 'messageCount' => $count);
         }
     }
     foreach ($totals2 as $count => $rows) {
         Streams_Total::insertManyAndExecute($rows, array('onDuplicateKeyUpdate' => array('messageCount' => new Db_Expression("messageCount + {$count}"))));
     }
     if ($messages2) {
         Streams_Message::insertManyAndExecute($messages2);
     }
     // time to update the stream rows and commit the transaction
     // on all the shards where the streams were fetched.
     foreach ($updates as $publisherId => $arr) {
         foreach ($arr as $count => $streamNames) {
             $suffix = is_numeric($count) ? " + {$count}" : '';
             Streams_Stream::update()->set(array('messageCount' => new Db_Expression('messageCount' . $suffix)))->where(array('publisherId' => $publisherId, 'name' => $streamNames))->commit()->execute();
         }
     }
     // handle all the events for successfully posting
     foreach ($posted as $publisherId => $arr) {
         foreach ($arr as $streamName => $messages3) {
             $stream = $streams[$publisherId][$streamName];
             foreach ($messages3 as $i => $message) {
                 $params = $eventParams[$publisherId][$streamName][$i];
                 /**
                  * @event Streams/message/$messageType {after}
                  * @param {string} publisherId
                  * @param {Streams_Stream} stream
                  * @param {string} message
                  */
                 Q::event("Streams/message/{$message->type}", $params, 'after', false);
                 /**
                  * @event Streams/post/$streamType {after}
                  * @param {string} publisherId
                  * @param {Streams_Stream} stream
                  * @param {string} message
                  */
                 Q::event("Streams/post/{$stream->type}", $params, 'after', false);
             }
         }
     }
     /**
      * @event Streams/postMessages {after}
      * @param {string} publisherId
      * @param {Streams_Stream} stream
      * @param {string} posted
      */
     Q::event("Streams/postMessages", array('streams' => $streams, 'messages' => $messages, 'skipAccess' => $skipAccess, 'posted' => $posted), 'after', false);
     if ($sendToNode) {
         Q_Utils::sendToNode(array("Q/method" => "Streams/Message/postMessages", "posted" => Q::json_encode($messages2), "streams" => Q::json_encode(Db::exportArray($streams))));
     }
     return array($posted, $streams);
 }
Пример #21
0
/**
 * Access tool
 * @class Streams access
 * @constructor
 * @param {array} $options Options for the tool
 * @param {string} [$options.publisherId] the id of the user who is publishing the stream
 * @param {string} [$options.streamName] the name of the stream for which to edit access levels
 * @param {array} [$options.tabs] array of tab name => title. Defaults to read, write, admin tabs.
 * @param {array} [$options.ranges] associative array with keys "read", "write", "admin" and values as associative arrays of ($min, $max) for the displayed levels.
 * @param {boolean} [$options.controls] optionally set this to true to render only the controls
 */
function Streams_access_tool($options)
{
    $tabs = array('read' => 'visible to', 'write' => 'editable by', 'admin' => 'members');
    extract($options);
    $user = Users::loggedInUser(true);
    /**
     * @var string $streamName
     */
    if (empty($streamName)) {
        $streamName = Streams::requestedName(true);
    }
    if (empty($publisherId)) {
        $publisherId = Streams::requestedPublisherId();
        if (empty($publisherId)) {
            $publisherId = $user->id;
        }
    }
    reset($tabs);
    $tab = Q::ifset($_REQUEST, 'tab', key($tabs));
    $stream = Streams::fetchOne($user->id, $publisherId, $streamName);
    if (!$stream) {
        throw new Q_Exception_MissingRow(array('table' => 'stream', 'criteria' => 'with that name'));
    }
    $stream->addPreloaded($user->id);
    if (!$stream->testAdminLevel('own')) {
        throw new Users_Exception_NotAuthorized();
    }
    $access_array = Streams_Access::select('*')->where(array('publisherId' => $stream->publisherId, 'streamName' => $stream->name))->andWhere("{$tab}Level != -1")->fetchDbRows();
    $labelRows = Users_Label::fetch($stream->publisherId, '', true);
    $labels = array();
    $icons = array();
    foreach ($labelRows as $label => $row) {
        $labels[$label] = $row->title;
        $icons[$label] = "labels/{$label}";
    }
    $userId_list = array();
    foreach ($access_array as $a) {
        if ($a->ofUserId) {
            $userId_list[] = $a->ofUserId;
        }
    }
    $avatar_array = empty($userId_list) ? array() : Streams_Avatar::fetch($user->id, $userId_list);
    switch ($tab) {
        case 'read':
            $levels = Q_Config::get('Streams', 'readLevelOptions', array());
            break;
        case 'write':
            $levels = Q_Config::get('Streams', 'writeLevelOptions', array());
            break;
        case 'admin':
            $levels = Q_Config::get('Streams', 'adminLevelOptions', array());
            break;
    }
    if (isset($ranges[$tab])) {
        $range_min = reset($ranges[$tab]);
        $range_max = end($ranges[$tab]);
        foreach ($levels as $k => $v) {
            if ($k < $range_min) {
                unset($levels[$k]);
            }
            if ($k > $range_max) {
                unset($levels[$k]);
            }
        }
    }
    $accessActionUrl = Q_Uri::url("Streams/access?publisherId={$publisherId}&streamName={$streamName}");
    $dir = Q_Config::get('Users', 'paths', 'icons', 'files/Users/icons');
    $accessArray = Db::exportArray($access_array);
    $avatarArray = Db::exportArray($avatar_array);
    if (empty($controls)) {
        Q_Response::addScript("plugins/Streams/js/Streams.js");
        Q_Response::addScript("plugins/Streams/js/tools/access.js");
        Q_Response::setToolOptions(compact('accessArray', 'avatarArray', 'labels', 'icons', 'tab', 'publisherId', 'streamName'));
    } else {
        Q_Response::setSlot('extra', array('stream' => $stream->exportArray(), 'accessArray' => $accessArray, 'avatarArray' => $avatarArray, 'labels' => $labels, 'icons' => $icons));
    }
    return Q::view('Streams/tool/access.php', compact('stream', 'tabs', 'tab', 'labels', 'icons', 'levels', 'dir', 'publisherId', 'streamName', 'accessActionUrl', 'controls'));
}