function Streams_0_8_1_Streams_mysql() { $app = Q_Config::expect('Q', 'app'); // template for community stream $stream = new Streams_Stream(); $stream->publisherId = ''; $stream->name = 'Streams/community/'; $stream->type = 'Streams/template'; $stream->title = "Community"; $stream->content = ''; $readLevel = Streams::$READ_LEVEL['content']; $writeLevel = Streams::$WRITE_LEVEL['join']; $adminLevel = Streams::$ADMIN_LEVEL['invite']; $stream->save(); // app community stream, for announcements $stream = new Streams_Stream(); $stream->publisherId = $app; $stream->name = 'Streams/community/main'; $stream->type = 'Streams/community'; $stream->title = "{$app} Community"; $stream->save(); // symlink the labels folder $cwd = getcwd(); chdir(USERS_PLUGIN_FILES_DIR . DS . 'Users' . DS . 'icons'); if (!file_exists('Streams')) { symlink(STREAMS_PLUGIN_FILES_DIR . DS . 'Streams' . DS . 'icons' . DS . 'labels' . DS . 'Streams', 'Streams'); } chdir($cwd); }
function Users_user_response_data($params) { // Get Gravatar info // WARNING: INTERNET_REQUEST $hash = md5(strtolower(trim($identifier))); $thumbnailUrl = Q_Request::baseUrl() . "/action.php/Users/thumbnail?hash={$hash}&size=80&type=" . Q_Config::get('Users', 'login', 'iconType', 'wavatar'); $json = @file_get_contents("http://www.gravatar.com/{$hash}.json"); $result = json_decode($json, true); if ($result) { if ($type === 'email') { $result['emailExists'] = !empty($exists); } else { if ($type === 'mobile') { $result['mobileExists'] = !empty($exists); } } return $result; } // otherwise, return default $email_parts = explode('@', $identifier, 2); $result = array("entry" => array(array("id" => "571", "hash" => "357a20e8c56e69d6f9734d23ef9517e8", "requestHash" => "357a20e8c56e69d6f9734d23ef9517e8", "profileUrl" => "http://gravatar.com/test", "preferredUsername" => ucfirst($email_parts[0]), "thumbnailUrl" => $thumbnailUrl, "photos" => array(), "displayName" => "", "urls" => array()))); if ($type === 'email') { $result['emailExists'] = !empty($exists); } else { $result['mobileExists'] = !empty($exists); } if ($terms_label = Users::termsLabel('register')) { $result['termsLabel'] = $terms_label; } return $result; }
function Q_response_dashboard() { $app = Q_Config::expect('Q', 'app'); $slogan = "Powered by Q."; $user = Users::loggedInUser(); return Q::view("{$app}/dashboard.php", compact('slogan', 'user')); }
function Overlay_before_Q_responseExtras() { $app = Q_Config::expect('Q', 'app'); Q_Response::addStylesheet('plugins/Q/css/Q.css'); Q_Response::addStylesheet('css/Overlay.css', '@end'); Q_Response::addStylesheet('http://fonts.googleapis.com/css?family=Open+Sans:400italic,400,300,700'); if (Q_Config::get('Q', 'firebug', false)) { Q_Response::addScript("https://getfirebug.com/firebug-lite-debug.js"); } Q_Response::addScript('js/Overlay.js'); Q_Response::setMeta("title", "Customize My Pic!"); Q_Response::setMeta("description", "Make a statement on Facebook by customizing your profile picture, even from your smartphone."); Q_Response::setMeta("image", Q_Html::themedUrl('img/icon/icon.png')); if (Q_Request::isIE()) { header("X-UA-Compatible", "IE=edge"); } header('Vary: User-Agent'); // running an event for loading action-specific extras (if there are any) $uri = Q_Dispatcher::uri(); $module = $uri->module; $action = $uri->action; $event = "{$module}/{$action}/response/responseExtras"; if (Q::canHandle($event)) { Q::event($event); } }
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'); }
/** * Used by HTTP clients to upload a new file to the server * @class Q/file * @method post * @param {array} [$params] Parameters that can come from the request * @param {string} [$params.data] Required if $_FILES is empty. Base64-encoded image data URI - see RFC 2397 * @param {string} [$params.path="uploads"] parent path under web dir (see subpath) * @param {string} [$params.subpath=""] subpath that should follow the path, to save the image under * @param {string} [$params.name] override the name of the file, after the subpath */ function Q_file_post($params = null) { $p = $params ? $params : Q::take($_REQUEST, array('data', 'path', 'subpath')); if (!empty($_FILES)) { $file = reset($_FILES); if ($tmp = $file['tmp_name']) { if (empty($p['data'])) { $p['data'] = file_get_contents($tmp); $p['name'] = $file['name']; } unlink($tmp); } } else { if (empty($p['data'])) { throw new Q_Exception_RequiredField(array('field' => 'data'), 'data'); } $p['data'] = base64_decode(chunk_split(substr($p['data'], strpos($p['data'], ',') + 1))); } $timeLimit = Q_Config::get('Q', 'uploads', 'limits', 'file', 'time', 5 * 60 * 60); set_time_limit($timeLimit); // default is 5 min $data = Q_File::save($p); if (empty($params)) { Q_Response::setSlot('data', $data); } return $data; }
function Streams_0_8_6_Streams_mysql() { $app = Q_Config::expect('Q', 'app'); // access for managing communities $access = new Streams_Access(); $access->publisherId = $app; $access->streamName = 'Streams/community*'; $access->ofUserId = ''; $access->ofContactLabel = "{$app}/admins"; $access->readLevel = Streams::$READ_LEVEL['messages']; $access->writeLevel = Streams::$WRITE_LEVEL['edit']; $access->adminLevel = Streams::$ADMIN_LEVEL['manage']; $access->save(); // access for managing categories $access = new Streams_Access(); $access->publisherId = $app; $access->streamName = 'Streams/category/'; $access->ofUserId = ''; $access->ofContactLabel = "{$app}/admins"; $access->readLevel = Streams::$READ_LEVEL['messages']; $access->writeLevel = Streams::$WRITE_LEVEL['close']; $access->adminLevel = Streams::$ADMIN_LEVEL['manage']; $access->save(); // template to help users relate things to Streams/category streams Streams_Stream::insert(array('publisherId' => '', 'name' => 'Streams/category/', 'type' => 'Streams/template', 'title' => 'Untitled Category', 'icon' => 'Streams/category', 'content' => '', 'attributes' => null, 'readLevel' => Streams::$READ_LEVEL['messages'], 'writeLevel' => Streams::$WRITE_LEVEL['relate'], 'adminLevel' => Streams::$ADMIN_LEVEL['invite']))->execute(); // template to help users create subcategories for things Streams_RelatedTo::insert(array('toPublisherId' => '', 'toStreamName' => 'Streams/category/', 'type' => 'subcategories', 'fromPublisherId' => '', 'fromStreamName' => 'Streams/category/'))->execute(); }
function Streams_interests_response() { // serve a javascript file and tell client to cache it $app = Q_Config::expect('Q', 'app'); $communityId = Q::ifset($_REQUEST, 'communityId', $app); $tree = new Q_Tree(); $tree->load("files/Streams/interests/{$communityId}.json"); $categories = $tree->getAll(); foreach ($categories as $category => &$v1) { foreach ($v1 as $k2 => &$v2) { if (!Q::isAssociative($v2)) { ksort($v1); break; } ksort($v2); } } header('Content-Type: text/javascript'); header("Pragma: ", true); // 1 day header("Cache-Control: public, max-age=86400"); // 1 day $expires = date("D, d M Y H:i:s T", time() + 86400); header("Expires: {$expires}"); // 1 day $json = Q::json_encode($categories, true); echo "Q.setObject(['Q', 'Streams', 'Interests', 'all', '{$communityId}'], {$json});"; return false; }
/** * Override Q/noModule handler. * just goes on to render our app's response, * which will echo a 404 view. */ function Q_noModule($params) { header("HTTP/1.0 404 Not Found"); Q_Dispatcher::uri()->module = Q_Config::expect('Q', 'app'); Q_Dispatcher::uri()->action = 'notFound'; Q::event('Q/response', $params); }
function Q_errors_native($params) { echo Q::view('Q/errors.php', $params); $app = Q_Config::expect('Q', 'app'); Q::log("{$app}: Errors in " . ceil(Q::milliseconds()) . "ms\n"); Q::log($params); }
function Broadcast_before_Streams_message_Broadcast($params) { extract($params); if (!empty($_REQUEST['link'])) { $parts = parse_url($_REQUEST['link']); if (empty($parts['host'])) { throw new Q_Exception_WrongType(array('field' => 'link', 'type' => 'a valid url'), 'link'); } } $content = array(); foreach (array('link', 'description', 'picture') as $field) { if (!empty($_REQUEST[$field])) { $content[$field] = $_REQUEST[$field]; } } if (!empty($_REQUEST['content'])) { $content['message'] = $_REQUEST['content']; } if (!$content) { throw new Q_Exception_RequiredField(array('field' => 'content'), 'content'); } // Manually adding a link for 'Manage or Remove' $appUrl = Q_Config::get('Users', 'facebookApps', 'Broadcast', 'url', ''); $content['actions'] = Q::json_encode(array(array('name' => 'Manage or Remove', 'link' => $appUrl))); $message->broadcast_instructions = Q::json_encode($content); }
function Users_0_9_2_Users_mysql() { $app = Q_Config::expect('Q', 'app'); $communityId = Users::communityId(); $rows = Users_Session::select('COUNT(1)')->where($criteria)->fetchAll(PDO::FETCH_NUM); $count = $rows[0][0]; $limit = 100; $offset = 0; $sessions = Users_Session::select('*')->orderBy('id')->limit($limit, $offset)->caching(false)->fetchDbRows(); echo "Adding userId to sessions..."; while ($sessions) { foreach ($sessions as $s) { $parsed = Q::json_decode($s->content, true); if (empty($parsed['Users']['loggedInUser']['id'])) { continue; } $s->userId = $parsed['Users']['loggedInUser']['id']; } Users_Session::insertManyAndExecute($sessions, array('onDuplicateKeyUpdate' => array('userId' => new Db_Expression("VALUES(userId)")))); $min = min($offset + $limit, $count); echo "[100D"; echo "Updated {$min} of {$count} sessions"; $offset += $limit; if ($offset > $count) { break; } $sessions = Users_Session::select('*')->orderBy('id')->limit($limit, $offset)->caching(false)->fetchDbRows(); } echo "\n"; }
function Streams_0_8_8_Streams_mysql() { $app = Q_Config::expect('Q', 'app'); $user = Users_User::fetch($app, true); Streams::create($app, $app, 'Streams/resource', array('name' => 'Streams/invitations', 'readLevel' => 0, 'writeLevel' => 0, 'adminLevel' => 0)); Streams_Access::insert(array('publisherId' => $app, 'streamName' => "Streams/invitations", 'ofUserId' => '', 'grantedByUserId' => null, 'ofContactLabel' => "{$app}/admins", 'readLevel' => Streams::$READ_LEVEL['messages'], 'writeLevel' => Streams::$WRITE_LEVEL['close'], 'adminLevel' => Streams::$ADMIN_LEVEL['invite']))->execute(); }
/** * Displays an HTML document that can be printed, ideally with line breaks. * Uses a particular view for the layout. * @param {array} $_REQUEST * @param {string} $_REQUEST.invitingUserId Required. The id of the user that generated the invitations with a call to Streams::invite. * @param {string} $_REQUEST.batch Required. The name of the batch under which invitations were saved during a call to Streams::invite. * @param {string} [$_REQUEST.limit=100] The maximum number of invitations to show on the page * @param {string} [$_REQUEST.offset=0] Used for paging * @param {string} [$_REQUEST.title='Invitations'] Override the title of the document * @param {string} [$_REQUEST.layout='default'] The name of the layout to use for the HTML document * @see Users::addLink() */ function Streams_invitations_response() { Q_Request::requireFields(array('batch', 'invitingUserId'), true); $invitingUserId = $_REQUEST['invitingUserId']; $batch = $_REQUEST['batch']; $title = Q::ifset($_REQUEST, 'layout', 'title'); $layoutKey = Q::ifset($_REQUEST, 'layout', 'default'); $limit = min(1000, Q::ifset($_REQUEST, 'limit', 100)); $offset = Q::ifset($_REQUEST, 'offset', 0); $layout = Q_Config::expect('Streams', 'invites', 'layout', $layoutKey); $app = Q_Config::expect('Q', 'app'); $pattern = Streams::invitationsPath($invitingUserId) . DS . $batch . DS . "*.html"; $filenames = glob($pattern); $parts = array(); foreach ($filenames as $f) { if (--$offset > 0) { continue; } $parts[] = file_get_contents($f); if (--$limit == 0) { break; } } $content = implode("\n\n<div class='Q_pagebreak Streams_invitations_separator'></div>\n\n", $parts); echo Q::view($layout, compact('content', 'parts')); return false; }
/** * Displays an HTML document that can be printed, ideally with line breaks. * Uses a particular view for the layout. * @param {array} $_REQUEST * @param {string} $_REQUEST.invitingUserId Required. The id of the user that generated the invitations with a call to Streams::invite. * @param {string} $_REQUEST.batch Required. The name of the batch under which invitations were saved during a call to Streams::invite. * @param {string} [$_REQUEST.limit=100] The maximum number of invitations to show on the page * @param {string} [$_REQUEST.offset=0] Used for paging * @param {string} [$_REQUEST.title='Invitations'] Override the title of the document * @param {string} [$_REQUEST.layout='default'] The name of the layout to use for the HTML document * @see Users::addLink() */ function Streams_invitations_response() { Q_Request::requireFields(array('batch', 'invitingUserId'), true); $invitingUserId = $_REQUEST['invitingUserId']; $batch = $_REQUEST['batch']; $user = Users::loggedInUser(true); $stream = Streams::fetchOne(null, $invitingUserId, 'Streams/invitations', true); if (!$stream->testReadLevel('content')) { throw new Users_Exception_NotAuthorized(); } $title = Q::ifset($_REQUEST, 'layout', 'title'); $layoutKey = Q::ifset($_REQUEST, 'layout', 'default'); $limit = min(1000, Q::ifset($_REQUEST, 'limit', 100)); $offset = Q::ifset($_REQUEST, 'offset', 0); $layout = Q_Config::expect('Streams', 'invites', 'layout', $layoutKey); $pattern = Streams::invitationsPath($invitingUserId) . DS . $batch . DS . "*.html"; $filenames = glob($pattern); $parts = array(); foreach ($filenames as $f) { if (--$offset > 0) { continue; } $parts[] = file_get_contents($f); if (--$limit == 0) { break; } } $content = implode("\n\n<div class='Q_pagebreak Streams_invitations_separator'></div>\n\n", $parts); echo Q::view($layout, compact('title', 'content', 'parts')); return false; }
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 $defaults = Q_Config::get("Streams", "types", $stream->type, "invite", "dialog", Q_Config::get("Streams", "defaults", "invite", "dialog", array())); $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)); $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 Users_identifier_post() { $userId = Q::ifset($_REQUEST, 'userId', null); if (isset($userId)) { $user = Users_User::fetch($userId, true); if ($user->emailAddress or $user->mobileNumber) { throw new Q_Exception("This user is already able to log in and set their own email and mobile number."); } } else { $user = Users::loggedInUser(true); } $app = Q_Config::expect('Q', 'app'); $fields = array(); $identifier = Users::requestedIdentifier($type); if (!$type) { throw new Q_Exception("a valid email address or mobile number is required", array('identifier', 'mobileNumber', 'emailAddress')); } if ($type === 'email') { $subject = Q_Config::get('Users', 'transactional', 'identifier', 'subject', "Welcome! Verify your email address."); $view = Q_Config::get('Users', 'transactional', 'identifier', 'body', 'Users/email/addEmail.php'); $user->addEmail($identifier, $subject, $view, array(), array('html' => true)); } else { if ($type === 'mobile') { $view = Q_Config::get('Users', 'transactional', 'identifier', 'sms', 'Users/sms/addMobile.php'); $user->addMobile($identifier, $view); } } }
function Websites_before_Streams_Stream_save_Websites_article($params) { $stream = $params['stream']; $modifiedFields = $params['modifiedFields']; if ($stream->wasRetrieved()) { return; } $user = new Users_User(); if (empty($stream->userId) and empty($modifiedFields['userId'])) { if ($liu = Users::loggedInUser()) { $stream->userId = $liu->id; } else { throw new Q_Exception_RequiredField(array('field' => 'userId')); } } $user->id = $stream->userId; if (!$user->retrieve()) { throw new Users_Exception_NoSuchUser(); } $title = Streams::displayName($user, array('fullAccess' => true)); if (isset($title)) { $stream->title = $title; } $stream->icon = $user->iconUrl(); $s = Streams::fetchOne($user->id, $user->id, "Streams/user/icon"); if (!$s or !($sizes = $s->getAttribute('sizes', null))) { $sizes = Q_Config::expect('Users', 'icon', 'sizes'); sort($sizes); } $stream->setAttribute('sizes', $sizes); }
/** * Standard tool for making payments. * @class Assets payment * @constructor * @param {array} $options Override various options for this tool * @param {string} $options.payments can be "authnet" or "stripe" * @param {string} $options.amount the amount to pay. * @param {double} [$options.currency="usd"] the currency to pay in. (authnet supports only "usd") * @param {string} [$options.payButton] Can override the title of the pay button * @param {String} [$options.publisherId=Users::communityId()] The publisherId of the Assets/product or Assets/service stream * @param {String} [$options.streamName] The name of the Assets/product or Assets/service stream * @param {string} [$options.name=Users::communityName()] The name of the organization the user will be paying * @param {string} [$options.image] The url pointing to a square image of your brand or product. The recommended minimum size is 128x128px. * @param {string} [$options.description=null] A short name or description of the product or service being purchased. * @param {string} [$options.panelLabel] The label of the payment button in the Stripe Checkout form (e.g. "Pay {{amount}}", etc.). If you include {{amount}}, it will be replaced by the provided amount. Otherwise, the amount will be appended to the end of your label. * @param {string} [$options.zipCode] Specify whether Stripe Checkout should validate the billing ZIP code (true or false). The default is false. * @param {boolean} [$options.billingAddress] Specify whether Stripe Checkout should collect the user's billing address (true or false). The default is false. * @param {boolean} [$options.shippingAddress] Specify whether Checkout should collect the user's shipping address (true or false). The default is false. * @param {string} [$options.email=Users::loggedInUser(true)->emailAddress] You can use this to override the email address, if any, provided to Stripe Checkout to be pre-filled. * @param {boolean} [$options.allowRememberMe=true] Specify whether to include the option to "Remember Me" for future purchases (true or false). * @param {boolean} [$options.bitcoin=false] Specify whether to accept Bitcoin (true or false). * @param {boolean} [$options.alipay=false] Specify whether to accept Alipay ('auto', true, or false). * @param {boolean} [$options.alipayReusable=false] Specify if you need reusable access to the customer's Alipay account (true or false). */ function Assets_payment_tool($options) { Q_Valid::requireFields(array('payments', 'amount'), $options, true); if (empty($options['name'])) { $options['name'] = Users::communityName(); } if (!empty($options['image'])) { $options['image'] = Q_Html::themedUrl($options['image']); } $options['payments'] = strtolower($options['payments']); if (empty($options['email'])) { $options['email'] = Users::loggedInUser(true)->emailAddress; } $payments = ucfirst($options['payments']); $currency = strtolower(Q::ifset($options, 'currency', 'usd')); if ($payments === 'Authnet' and $currency !== 'usd') { throw new Q_Exception("Authnet doesn't support currencies other than USD", 'currency'); } $className = "Assets_Payments_{$payments}"; switch ($payments) { case 'Authnet': $adapter = new $className($options); $token = $options['token'] = $adapter->authToken(); $testing = $options['testing'] = Q_Config::expect('Assets', 'payments', $lcpayments, 'testing'); $action = $options['action'] = $testing ? "https://test.authorize.net/profile/manage" : "https://secure.authorize.net/profile/manage"; break; case 'Stripe': $publishableKey = Q_Config::expect('Assets', 'payments', 'stripe', 'publishableKey'); break; } $titles = array('Authnet' => 'Authorize.net', 'Stripe' => 'Stripe'); Q_Response::setToolOptions($options); $payButton = Q::ifset($options, 'payButton', "Pay with " . $titles[$payments]); return Q::view("Assets/tool/payment/{$payments}.php", compact('token', 'publishableKey', 'action', 'payButton')); }
function Users_after_Q_reroute($params, &$stop_dispatch) { $uri = Q_Dispatcher::uri(); $app = Q_Config::expect('Q', 'app'); $ma = $uri->module . '/' . $uri->action; $requireLogin = Q_Config::get('Users', 'requireLogin', array()); if (!isset($requireLogin[$ma])) { return; // We don't have to require login here } $user = Users::loggedInUser(); if ($requireLogin[$ma] === true and !$user) { // require login } else { if ($requireLogin[$ma] === 'facebook' and !Users::facebook($app)) { // require facebook } else { return; // We don't have to require login here } } $redirect_action = Q_Config::get('Users', 'uris', "{$app}/login", "{$app}/welcome"); if ($redirect and $ma != $redirect_action) { Q_Response::redirect($redirect_action); $stop_dispatch = true; return; } }
/** * Used to create a new stream * * @param {array} $_REQUEST * @param {String} [$_REQUEST.title] Required. The title of the interest. * @param {String} [$_REQUEST.publisherId] Optional. Defaults to the app name. * @return {void} */ function Streams_interest_delete() { $user = Users::loggedInUser(true); $title = Q::ifset($_REQUEST, 'title', null); if (!isset($title)) { throw new Q_Exception_RequiredField(array('field' => 'title')); } $app = Q_Config::expect('Q', 'app'); $publisherId = Q::ifset($_REQUEST, 'publisherId', $app); $name = 'Streams/interest/' . Q_Utils::normalize($title); $stream = Streams::fetchOne(null, $publisherId, $name); if (!$stream) { throw new Q_Exception_MissingRow(array('table' => 'stream', 'criteria' => Q::json_encode(compact('publisherId', 'name')))); } $miPublisherId = $user->id; $miName = 'Streams/user/interests'; $myInterests = Streams::fetchOne($user->id, $miPublisherId, $miName); if (!$myInterests) { throw new Q_Exception_MissingRow(array('table' => 'stream', 'criteria' => Q::json_encode(array('publisherId' => $miPublisherId, 'name' => $miName)))); } $stream->leave(); Streams::unrelate($user->id, $user->id, 'Streams/user/interests', 'Streams/interest', $publisherId, $name, array('adjustWeights' => true)); Q_Response::setSlot('publisherId', $publisherId); Q_Response::setSlot('streamName', $name); /** * Occurs when the logged-in user has successfully removed an interest via HTTP * @event Streams/interest/delete {after} * @param {string} publisherId The publisher of the interest stream * @param {string} title The title of the interest * @param {Users_User} user The logged-in user * @param {Streams_Stream} stream The interest stream * @param {Streams_Stream} myInterests The user's "Streams/user/interests" stream */ Q::event("Streams/interest/remove", compact('publisherId', 'title', 'subscribe', 'user', 'stream', 'myInterests'), 'after'); }
/** * Call this function to find the "nearby points" to subscribe to * on a grid of quantized (latitude, longitude) pairs * which are spaced at most $miles apart. * @param {double} $latitude The latitude of the coordinates to search around * @param {double} $longitude The longitude of the coordinates to search around * @param {double} $miles The radius, in miles, around this location. * Should be one of the array values in the Places/nearby/miles config. * @return {Array} Returns an array of up to four ($streamName => $info) pairs * where the $streamName is the name of the stream corresponding to the "nearby point" * and $info includes the keys "latitude", "longitude", and "miles". */ static function forSubscribers($latitude, $longitude, $miles) { list($latQuantized, $longQuantized, $latGrid, $a) = Places::quantize($latitude, $longitude, $miles); $milesArray = Q_Config::expect('Places', 'nearby', 'miles'); if (!in_array($miles, $milesArray)) { throw new Q_Exception("The miles value needs to be in Places/nearby/miles config."); } $result = array(); foreach (array($latQuantized, $latQuantized + $latGrid * 1.1) as $lat) { list($a, $b, $c, $longGrid) = Places::quantize($lat, $longitude, $miles); foreach (array($longQuantized, $longQuantized + $longGrid * 1.1) as $long) { list($latQ, $longQ) = Places::quantize($lat, $long, $miles); if ($longQ > 180) { $longQ = $long % 180 - 180; } if ($longQ < -180) { $longQ = $long % 180 + 180; } if ($latQ > 90) { $latQ = $latQ % 90 - 90; } if ($latQ < -90) { $latQ = $latQ % 90 + 90; } $streamName = self::streamName($latQ, $longQ, $miles); $result[$streamName] = array('latitude' => $lat, 'longitude' => $long, 'geohash' => Places_Geohash::encode($latQ, $longQ, 6), 'miles' => $miles); } } return $result; }
function Broadcast_control_response_content($params) { $user = Users::loggedInUser(true); $organizations = Broadcast_Agreement::select('a.userId, a.publisherId, u.organization_title, u.organization_domain', 'a')->join(Broadcast_User::table() . ' u', array('a.publisherId' => 'u.userId'))->where(array('a.userId' => $user->id))->fetchAll(PDO::FETCH_ASSOC); foreach ($organizations as $k => $org) { $messages = Streams_Message::select('content')->where(array('publisherId' => $org['publisherId'], 'streamName' => 'Broadcast/main'))->orderBy('sentTime')->fetchAll(PDO::FETCH_ASSOC); $organizations[$k]['messages'] = array(); foreach ($messages as $msg) { $content = json_decode($msg['content'], true); if (isset($content['link'])) { $ch = curl_init(); $timeout = 5; curl_setopt($ch, CURLOPT_URL, $content['link']); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (X11; U; Linux i686; cs-CZ; rv:1.7.12) Gecko/20050929"); $page_contents = curl_exec($ch); curl_close($ch); preg_match('/<title>([^<]+)<\\/title>/', $page_contents, $matches); if (isset($matches[1])) { $content['link_title'] = $matches[1]; } } $organizations[$k]['messages'][] = $content; } } Q_Config::set('Q', 'response', 'Broadcast', 'layout_html', 'Broadcast/layout/canvas.php'); Q_Response::addStylesheet('css/canvas.css'); Q_Response::addScript('http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js'); Q_Response::addScript('js/canvas.js'); return Q::view('Broadcast/content/control.php', compact('organizations')); }
function Streams_before_Q_responseExtras() { Q_Response::addScript('plugins/Streams/js/Streams.js'); $host = Q_Config::get('Streams', 'node', 'host', Q_Config::get('Q', 'node', 'host', null)); $port = Q_Config::get('Streams', 'node', 'port', Q_Config::get('Q', 'node', 'port', null)); $user = Users::loggedInUser(); if ($user) { Q_Response::setScriptData('Q.plugins.Users.loggedInUser.displayName', Streams::displayName($user)); } if (!Q_Request::isAjax()) { $invite_url = Q_Config::get('Streams', 'invite', 'url', "http://invites.to"); Q_Response::setScriptData('Q.plugins.Streams.invite.url', $invite_url); if (isset($host) && isset($port)) { Q_Response::setScriptData('Q.plugins.Streams.node', array("http://{$host}:{$port}")); } if ($sizes = Q_Config::expect('Streams', 'types', 'Streams/image', 'sizes')) { sort($sizes); Q_Response::setScriptData('Q.plugins.Streams.image.sizes', $sizes); } $defaults = array('readLevel' => Streams::$READ_LEVEL['messages'], 'writeLevel' => Streams::$WRITE_LEVEL['join'], 'adminLevel' => Streams::$ADMIN_LEVEL['invite']); Q_Response::setScriptData('Q.plugins.Streams.defaults', $defaults); if ($froalaKey = Q_Config::get('Streams', 'froala', 'key', null)) { Q_Response::setScriptData('Q.plugins.Streams.froala.key', $froalaKey); } } Q_Response::addStylesheet("plugins/Streams/css/Streams.css"); }
/** * @constructor * @param {array} $options=array() Any initial options * @param {string} $options.secret * @param {string} $options.publishableKey * @param {string} $options.token If provided, allows us to create a customer and charge them * @param {Users_User} [$options.user=Users::loggedInUser()] Allows us to set the user to charge */ function __construct($options = array()) { if (!isset($options['user'])) { $options['user'] = Users::loggedInUser(true); } $this->options = array_merge(array('secret' => Q_Config::expect('Assets', 'payments', 'stripe', 'secret'), 'publishableKey' => Q_Config::expect('Assets', 'payments', 'stripe', 'publishableKey')), $options); }
function Users_user_validate() { Q_Valid::nonce(true); $type = isset($_REQUEST['identifierType']) ? $_REQUEST['identifierType'] : Q_Config::get("Users", "login", "identifierType", "email,mobile"); $parts = explode(',', $type); $accept_mobile = true; $expected = 'email address or mobile number'; $fields = array('emailAddress', 'mobileNumber', 'identifier'); if (count($parts) === 1) { if ($parts[0] === 'email') { $expected = 'email address'; $fields = array('emailAddress', 'identifier'); $accept_mobile = false; } else { if ($parts[0] === 'mobile') { $expected = 'mobile number'; $fields = array('mobileNumber', 'identifier'); } } } if (!isset($_REQUEST['identifier'])) { throw new Q_Exception("a valid {$expected} is required", $fields); } if (!Q_Valid::email($_REQUEST['identifier'])) { if (!$accept_mobile) { throw new Q_Exception("a valid {$expected} is required", $fields); } if (!Q_Valid::phone($_REQUEST['identifier'])) { throw new Q_Exception("a valid {$expected} is required", $fields); } } }
/** * Standard tool for starting or managing subscriptions. * @class Assets subscription * @constructor * @param {array} $options Override various options for this tool * @param {string} $options.payments can be "authnet" or "stripe" * @param {string} $options.planStreamName the name of the subscription plan's stream * @param {string} [$options.publisherId=Q.Users.communityId] the publisher of the subscription plan's stream * @param {string} [$options.subscribeButton] Can override the title of the subscribe button * @param {array} [$options=array()] Any additional options * @param {string} [$options.token=null] required unless the user is an existing customer */ function Assets_subscription_tool($options) { if (empty($options['payments'])) { throw new Q_Exception_RequiredField(array('field' => 'payments'), 'payments'); } $payments = ucfirst($options['payments']); $lcpayments = strtolower($payments); $currency = strtolower(Q::ifset($options, 'currency', 'usd')); if ($payments === 'Authnet' and $currency !== 'usd') { throw new Q_Exception("Authnet doesn't support currencies other than USD", 'currency'); } $className = "Assets_Payments_{$payments}"; switch ($payments) { case 'Authnet': $adapter = new $className($options); $token = $options['token'] = $adapter->authToken(); $testing = $options['testing'] = Q_Config::expect('Assets', 'payments', $lcpayments, 'testing'); $action = $options['action'] = $testing ? "https://test.authorize.net/profile/manage" : "https://secure.authorize.net/profile/manage"; break; case 'Stripe': $publishableKey = Q_Config::expect('Assets', 'payments', 'stripe', 'publishableKey'); break; } $titles = array('Authnet' => 'Authorize.net', 'Stripe' => 'Stripe'); $subscribeButton = Q::ifset($options, 'subscribeButton', "Subscribe with " . $titles[$payments]); Q_Response::setToolOptions($options); return Q::view("Assets/tool/subscription/{$payments}.php", compact('token', 'publishableKey', 'action', 'paymentButton', 'subscribeButton', 'planStreamName')); }
/** * Used to post messages to EXISTING stream * $_REQUEST shall contain the content of the message. Also may include 'streamNames' * field which is an array of additional names of the streams to post message to. * * @param string $params * publisher id and stream name of existing stream shall be supplied * @return {void} */ function Streams_message_post() { $user = Users::loggedInUser(true); $publisherId = Streams::requestedPublisherId(true); $streamName = Streams::requestedName(true); // check if type is allowed $streams = Streams::fetch($user->id, $publisherId, $streamName); if (empty($streams)) { throw new Streams_Exception_NoSuchStream(); } $stream = reset($streams); if (empty($_REQUEST['type'])) { throw new Q_Exception_RequiredField(array('field' => 'type'), 'type'); } $type = $_REQUEST['type']; if (!Q_Config::get("Streams", "types", $stream->type, "messages", $type, 'post', false)) { throw new Q_Exception("This app doesn't support directly posting messages of type '{$type}' for streams of type '{$stream->type}'"); } $result = Streams_Message::post($user->id, $publisherId, $streamName, $_REQUEST); if (is_array($result)) { Streams::$cache['messages'] = $result; } else { Streams::$cache['message'] = $result; } }
/** * This tool renders a user avatar * * @param {array} $options An associative array of parameters, containing: * @param {boolean} [$options.userId] * "userId" => The user's id. Defaults to id of the logged-in user, if any. * @param {boolean} [$options.icon] * "icon" => Optional. Render icon before the username. * @param {boolean} [$options.iconAttributes] * "iconAttributes" => Optional. Array of attributes to render for the icon. * @param {boolean} [$options.editable] * "editable" => Optional. Whether to provide an interface for editing the user's info. Can be array containing "icon", "name". * @param {array} [$options.inplaces] Additional fields to pass to the child Streams/inplace tools, if any * @param {boolean} [$options.renderOnClient] * If true, only the html container is rendered, so the client will do the rest. */ function Users_avatar_tool($options) { $defaults = array('icon' => false, 'editable' => false); $options = array_merge($defaults, $options); if (empty($options['userId'])) { $user = Users::loggedInUser(); $options['userId'] = $user->id; } else { $user = Users_User::fetch($options['userId']); } Q_Response::addStylesheet('plugins/Q/css/Q.css'); Q_Response::setToolOptions($options); if (!empty($options['renderOnClient'])) { return ''; } if (!$user) { return ''; } $user->addPreloaded(); $p = $options; $p['userId'] = $user->id; Q_Response::setToolOptions($p); $result = ''; $icon = $options['icon']; if ($icon) { if ($icon === true) { $icon = Q_Config::get('Users', 'icon', 'defaultSize', 40); } $attributes = isset($options['iconAttributes']) ? $options['iconAttributes'] : array(); $attributes['class'] = isset($attributes['class']) ? $attributes['class'] . ' Users_avatar_icon' : 'Users_avatar_icon'; $result .= Q_Html::img($user->iconUrl($icon), 'user icon', $attributes); } $result .= '<span class="Users_avatar_name">' . $user->username . '</span>'; return $result; }
function Streams_invite_validate() { if (Q_Request::method() === 'PUT') { return; } if (Q_Request::method() !== 'GET') { Q_Valid::nonce(true); } $fields = array('publisherId', 'streamName'); if (Q_Request::method() === 'POST') { if (Q_Valid::requireFields($fields)) { return; } foreach ($fields as $f) { if (strlen(trim($_REQUEST[$f])) === 0) { Q_Response::addError(new Q_Exception("{$f} can't be empty", $f)); } } } if (isset($_REQUEST['fullName'])) { $length_min = Q_Config::get('Streams', 'inputs', 'fullName', 'lengthMin', 5); $length_max = Q_Config::get('Streams', 'inputs', 'fullName', 'lengthMax', 30); if (strlen($_REQUEST['fullName']) < $length_min) { throw new Q_Exception("A user's full name can't be that short.", 'fullName'); } if (strlen($_REQUEST['fullName']) > $length_max) { throw new Q_Exception("A user's full name can't be that long.", 'fullName'); } } }