function Streams_invite_response_data() { if (isset(Streams::$cache['invited'])) { return Streams::$cache['invited']; } $user = Users::loggedInUser(true); $publisherId = Streams::requestedPublisherId(); $streamType = Streams::requestedType(); $invitingUserId = Streams::requestedField('invitingUserId'); $limit = Q::ifset($_REQUEST, 'limit', Q_Config::get('Streams', 'invites', 'limit', 100)); $invited = Streams_Invited::select('*')->where(array('userId' => $user->id, 'state' => 'pending', 'expireTime <' => new Db_Expression('CURRENT_TIMESTAMP')))->limit($limit)->fetchDbRows(null, null, 'token'); $query = Streams_Invite::select('*')->where(array('token' => array_keys($invited))); if (isset($publisherId)) { $query = $query->where(array('publisherId' => $publisherId)); } if (isset($streamType)) { $query = $query->where(array('streamName' => new Db_Range($streamType . '/', true, false, true))); } if (isset($invitingUserId)) { $query = $query->where(array('invitingUserId' => $invitingUserId)); } $invites = $query->fetchDbRows(); $streams = array(); foreach ($invites as $invite) { $stream = new Streams_Stream(); $stream->publisherId = $invite->publisherId; $stream->name = $invite->streamName; if ($stream->retrieve()) { $streams[$invite->token] = $stream->exportArray(); $streams[$invite->token]['displayName'] = $invite->displayName; } } return compact('streams', 'invites'); }
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_before_Streams_Participant_save($params) { $row = $params['row']; if (substr($row->streamName, 0, 18) === 'Streams/community/' and !$row->wasRetrieved()) { $communityId = $row->publisherId; $stream = new Streams_Stream(); $stream->publisherId = $row->userId; $stream->name = "Streams/greeting/{$communityId}"; if ($stream->retrieve()) { $row->setExtra('Streams/greeting', $stream->content); } } }
/** * Get a Places/location stream published by a publisher for a given placeId. * This is used to cache information from the Google Places API. * @method stream * @static * @param {string} $publisherId * @param {string} $placeId The id of the place in Google Places * @param {boolean} $throwIfBadValue * Whether to throw Q_Exception if the result contains a bad value * @return {Streams_Stream|null} * @throws {Q_Exception} if a bad value is encountered and $throwIfBadValue is true */ static function stream($publisherId, $placeId, $throwIfBadValue = false) { if (empty($placeId)) { if ($throwIfBadValue) { throw new Q_Exception_RequiredField(array('field' => 'id')); } return null; } // sanitize the ID $characters = '/[^A-Za-z0-9]+/'; $result = preg_replace($characters, '_', $placeId); // see if it's already in the system $location = new Streams_Stream(); $location->publisherId = $publisherId; $location->name = "Places/location/{$placeId}"; if ($location->retrieve()) { $ut = $location->updatedTime; if (isset($ut)) { $db = $location->db(); $ut = $db->fromDateTime($ut); $ct = $db->getCurrentTimestamp(); $cd = Q_Config::get('Places', 'cache', 'duration', 60 * 60 * 24 * 30); if ($ct - $ut < $cd) { // there is a cached location stream that is still viable return $location; } } } $key = Q_Config::expect('Places', 'google', 'keys', 'server'); $query = http_build_query(array('key' => $key, 'placeid' => $placeId)); $url = "https://maps.googleapis.com/maps/api/place/details/json?{$query}"; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $json = curl_exec($ch); curl_close($ch); $response = json_decode($json, true); if (empty($response['result'])) { throw new Q_Exception("Places_Location::stream: Couldn't obtain place information for {$placeId}"); } if (!empty($response['error_message'])) { throw new Q_Exception("Places_Location::stream: " . $response['error_message']); } $result = $response['result']; $attributes = array('title' => $result['name'], 'latitude' => $result['geometry']['location']['lat'], 'longitude' => $result['geometry']['location']['lng'], 'viewport' => $result['geometry']['viewport'], 'phoneNumber' => Q::ifset($result, 'international_phone_number', null), 'phoneFormatted' => Q::ifset($result, 'formatted_phone_number', null), 'rating' => Q::ifset($result, 'rating', null), 'address' => Q::ifset($result, 'formatted_address', null)); $location->title = $result['name']; $location->setAttribute($attributes); $location->type = 'Places/location'; $location->save(); return $location; }
function Broadcast_main_response_content() { Q_Response::addScript('plugins/Broadcast/js/Broadcast.js'); $user = Users::loggedInUser(true); $stream = new Streams_Stream(); $stream->publisherId = $user->id; $stream->name = 'Broadcast/main'; if (!$stream->retrieve()) { $stream->type = 'Broadcast'; $stream->title = "Main broadcast stream"; $stream->content = "Whatever you post to this stream will be syndicated by everyone who has opted in."; $stream->save(); } Q_Response::redirect('Broadcast/stream publisherId=' . $stream->publisherId . ' name=Broadcast/main'); }
function Streams_invite_response_content() { $user = Users::loggedInUser(true); $publisherId = Streams::requestedPublisherId(); if (empty($publisherId)) { $publisherId = $user->id; } $streamName = Streams::requestedName(true); $stream = new Streams_Stream(); $stream->publisherId = $publisherId; $stream->name = $streamName; if (!$stream->retrieve()) { throw new Q_Exception_MissingRow(array('table' => 'stream', 'criteria' => "{publisherId: '{$publisherId}', name: '{$streamName}'}")); } return Q::tool('Streams/invite', compact('stream')); }
function Streams_access_response_content($options) { $ajax = true; $user = Users::loggedInUser(true); $streamName = Streams::requestedName(true); $publisherId = Streams::requestedPublisherId(); if (empty($publisherId)) { $publisherId = $user->id; } $stream = new Streams_Stream(); $stream->publisherId = $publisherId; $stream->name = $streamName; if (!$stream->retrieve()) { throw new Q_Exception_MissingRow(array('table' => 'stream', 'criteria' => 'with that name'), 'name'); } $controls = !empty($options['controls']); Q_Response::setSlot('title', "Access to: " . $stream->title); return Q::tool('Streams/access', compact('publisherId', 'streamName', 'ajax', 'controls'), $controls ? array('tag' => null) : array()); }
/** * Check if user "owns" a stream template for a publisher * @method isOwner * @static * @param {string} $publisherId * @param {string} $type * @param {string|Users_User} [$user=null] * @return {boolean} */ static function isOwner($publisherId, $type, $user = null) { if (!isset($user)) { $user = Users::loggedInUser(); } else { if (is_string($user)) { $user = Users_User::fetch($user); } } if (!isset($user)) { return false; } // check if user is owner of stream template $stream = new Streams_Stream(); $stream->publisherId = $publisherId; $stream->name = $type . '/'; if (!$stream->retrieve()) { return false; } $stream->calculateAccess($user->id); return $stream->testAdminLevel('own'); }
/** * Closes a stream, which prevents anyone from posting messages to it * unless they have WRITE_LEVEL >= "close", as well as attempting to remove * all relations to other streams. A "cron job" can later go and delete * closed streams. The reason you should avoid deleting streams right away * is that other subscribers may still want to receive the last messages * posted to the stream. * @method close * @param {string} $asUserId The id of the user who would be closing the stream * @param {string} $publisherId The id of the user publishing the stream * @param {string} $streamName The name of the stream * @param {array} [$options=array()] Can include "skipAccess" * @static */ static function close($asUserId, $publisherId, $streamName, $options = array()) { $stream = new Streams_Stream(); $stream->publisherId = $publisherId; $stream->name = $streamName; if (!$stream->retrieve()) { throw new Q_Exception_MissingRow(array('table' => 'stream', 'criteria' => "{publisherId: '{$publisherId}', name: '{$streamName}'}")); } // Authorization check if (empty($options['skipAccess'])) { if ($asUserId !== $publisherId) { $stream->calculateAccess($asUserId); if (!$stream->testWriteLevel('close')) { throw new Users_Exception_NotAuthorized(); } } } // Clean up relations from other streams to this category list($relations, $related) = Streams::related($asUserId, $stream->publisherId, $stream->name, true); foreach ($relations as $r) { try { Streams::unrelate($asUserId, $r->fromPublisherId, $r->fromStreamName, $r->type, $stream->publisherId, $stream->name); } catch (Exception $e) { } } // Clean up relations from this stream to categories list($relations, $related) = Streams::related($asUserId, $stream->publisherId, $stream->name, false); foreach ($relations as $r) { try { Streams::unrelate($asUserId, $r->toPublisherId, $r->toStreamName, $r->type, $stream->publisherId, $stream->name); } catch (Exception $e) { } } $result = false; try { $db = $stream->db(); $stream->closedTime = $closedTime = $db->toDateTime($db->getCurrentTimestamp()); if ($stream->save()) { $stream->post($asUserId, array('type' => 'Streams/closed', 'content' => '', 'instructions' => compact('closedTime')), true); $result = true; } } catch (Exception $e) { throw $e; } return $result; }
/** * Send credits, as the logged-in user, to another user * @method send * @static * @param {integer} $amount The amount of credits to send. * @param {string} $toUserId The id of the user to whom you will send the credits * @param {array} $more An array supplying more info, including * "reason" => Identifies the reason for sending, if any */ static function send($amount, $toUserId, $more = array()) { if (!is_int($amount) or $amount <= 0) { throw new Q_Exception_WrongType(array('field' => 'amount', 'type' => 'integer')); } $user = Users::loggedInUser(true); $from_stream = new Streams_Stream(); $from_stream->publisherId = $user->id; $from_stream->name = 'Awards/credits'; if (!$from_stream->retrieve()) { $from_stream = self::createStream($user); } $existing_amount = $from_stream->getAttribute('amount'); if ($existing_amount < $amount) { throw new Awards_Exception_NotEnoughCredits(array('missing' => $amount - $existing_amount)); } $to_user = Users_User::fetch($toUserId, true); $to_stream = new Streams_Stream(); $to_stream->publisherId = $toUserId; $to_stream->name = 'Awards/credits'; if (!$to_stream->retrieve()) { $to_stream = self::createStream($to_user); } $to_stream->setAttribute('amount', $to_stream->getAttribute('amount') - $amount); $to_stream->save(); // NOTE: we are not doing transactions here mainly because of sharding. // If if we reached this point without exceptions, that means everything worked. // But if the following statement fails, then someone will get free credits. $from_stream->setAttribute('amount', $from_stream->getAttribute('amount') - $amount); $from_stream->save(); $instructions_json = Q::json_encode(array_merge(array('app' => Q_Config::expect('Q', 'app')), $more)); Streams_Message::post($user->id, $userId, array('type' => 'Awards/credits/sent', 'content' => $amount, 'instructions' => $instructions_json)); Streams_Message::post($user->id, $toUserId, array('type' => 'Awards/credits/received', 'content' => $amount, 'instructions' => $instructions_json)); }