Esempio n. 1
0
 /**
  * Helper function for walking the Mustache token parse tree.
  *
  * @throws {InvalidArgumentException} upon encountering unknown token types.
  *
  * @param array $tree  Parse tree of Mustache tokens
  * @param int   $level (default: 0)
  *
  * @return {string} Generated PHP source code
  */
 private function walk(array $tree, $level = 0)
 {
     $code = '';
     $level++;
     foreach ($tree as $node) {
         switch ($node[Mustache_Tokenizer::TYPE]) {
             case Mustache_Tokenizer::T_SECTION:
                 $code .= $this->section($node[Mustache_Tokenizer::NODES], $node[Mustache_Tokenizer::NAME], $node[Mustache_Tokenizer::INDEX], $node[Mustache_Tokenizer::END], $node[Mustache_Tokenizer::OTAG], $node[Mustache_Tokenizer::CTAG], $level);
                 break;
             case Mustache_Tokenizer::T_INVERTED:
                 $code .= $this->invertedSection($node[Mustache_Tokenizer::NODES], $node[Mustache_Tokenizer::NAME], $level);
                 break;
             case Mustache_Tokenizer::T_PARTIAL:
             case Mustache_Tokenizer::T_PARTIAL_2:
                 $code .= $this->partial($node[Mustache_Tokenizer::NAME], isset($node[Mustache_Tokenizer::INDENT]) ? $node[Mustache_Tokenizer::INDENT] : '', $level);
                 break;
             case Mustache_Tokenizer::T_UNESCAPED:
             case Mustache_Tokenizer::T_UNESCAPED_2:
                 $code .= $this->variable($node[Mustache_Tokenizer::NAME], false, $level);
                 break;
             case Mustache_Tokenizer::T_COMMENT:
                 break;
             case Mustache_Tokenizer::T_ESCAPED:
                 $code .= $this->variable($node[Mustache_Tokenizer::NAME], true, $level);
                 break;
             case Mustache_Tokenizer::T_TEXT:
                 $code .= $this->text($node[Mustache_Tokenizer::VALUE], $level);
                 break;
             default:
                 throw new InvalidArgumentException('Unknown node type: ' . Q::json_encode($node));
         }
     }
     return $code;
 }
Esempio n. 2
0
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;
}
Esempio n. 3
0
/**
 * 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');
}
Esempio n. 4
0
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);
}
Esempio n. 5
0
function Websites_seo_post()
{
    if (empty($_REQUEST['streamName'])) {
        throw new Q_Exception_RequiredField(array('field' => 'streamName'));
    }
    $prefix = "Websites/seo/";
    if (substr($_REQUEST['streamName'], 0, strlen($prefix)) !== $prefix) {
        throw new Q_Exception_WrongValue(array('field' => 'streamName', 'range' => "string beginning with {$prefix}"));
    }
    $user = Users::loggedInUser(true);
    $publisherId = Users::communityId();
    $type = "Websites/seo";
    if (!Streams::isAuthorizedToCreate($user->id, $publisherId, $type)) {
        throw new Users_Exception_NotAuthorized();
    }
    $stream = new Streams_Stream($publisherId);
    $stream->publisherId = $publisherId;
    $stream->name = $_REQUEST['streamName'];
    $stream->type = $type;
    if (isset($_REQUEST['uri'])) {
        $stream->setAttribute('uri', $_REQUEST['uri']);
    }
    $stream->save();
    $stream->post($user->id, array('type' => 'Streams/created', 'content' => '', 'instructions' => Q::json_encode($stream->toArray())), true);
    $stream->subscribe();
    // autosubscribe to streams you yourself create, using templates
    Q_Response::setSlot('stream', $stream->exportArray());
}
Esempio n. 6
0
function Users_before_Q_session_save($params)
{
    $row = $params['row'];
    $row->deviceId = "";
    $row->timeout = 0;
    $row->content = isset($_SESSION) ? Q::json_encode($_SESSION, JSON_FORCE_OBJECT) : "{}";
    $row->duration = Q_Config::get('Q', 'session', 'durations', Q_Request::formFactor(), Q_Config::expect('Q', 'session', 'durations', 'session'));
}
Esempio n. 7
0
/**
 * This tool contains functionality to show things in columns
 * @class Q columns
 * @constructor
 * @param {array}   [options] Provide options for this tool
 *  @param {array}  [options.animation] For customizing animated transitions
 *  @param {integer}  [options.animation.duration] The duration of the transition in milliseconds, defaults to 500
 *  @param {array}  [options.animation.hide] The css properties in "hide" state of animation
 *  @param {array}  [options.animation.show] The css properties in "show" state of animation
 *  @param {array}  [options.back] For customizing the back button on mobile
 *  @param {string}  [options.back.src] The src of the image to use for the back button
 *  @param {boolean} [options.back.triggerFromTitle] Whether the whole title would be a trigger for the back button. Defaults to true.
 *  @param {boolean} [options.back.hide] Whether to hide the back button. Defaults to false, but you can pass true on android, for example.
 *  @param {array}  [options.close] For customizing the back button on desktop and tablet
 *  @param {string}  [options.close.src] The src of the image to use for the close button
 *  @param {string}  [options.title] You can put a default title for all columns here (which is shown as they are loading)
 *  @param {string}  [options.column] You can put a default content for all columns here (which is shown as they are loading)
 *  @param {array}  [options.clickable] If not null, enables the Q/clickable tool with options from here. Defaults to null.
 *  @param {array}  [options.scrollbarsAutoHide] If not null, enables Q/scrollbarsAutoHide functionality with options from here. Enabled by default.
 *  @param {boolean} [options.fullscreen] Whether to use fullscreen mode on mobile phones, using document to scroll instead of relying on possibly buggy "overflow" CSS implementation. Defaults to true on Android, false everywhere else.
 *  @param {array}   [options.columns] In PHP only, an array of $name => $column pairs, where $column is in the form array('title' => $html, 'content' => $html, 'close' => true)
 * @return {string}
 */
function Q_columns_tool($options)
{
    $jsOptions = array('animation', 'back', 'close', 'title', 'scrollbarsAutoHide', 'fullscreen');
    Q_Response::setToolOptions(Q::take($options, $jsOptions));
    if (!isset($options['columns'])) {
        return '';
    }
    Q_Response::addScript('plugins/Q/js/tools/columns.js');
    Q_Response::addStylesheet('plugins/Q/css/columns.css');
    $result = '<div class="Q_columns_container Q_clearfix">';
    $columns = array();
    $i = 0;
    $closeSrc = Q::ifset($options, 'close', 'src', 'plugins/Q/img/x.png');
    $backSrc = Q::ifset($options, 'back', 'src', 'plugins/Q/img/back-v.png');
    foreach ($options['columns'] as $name => $column) {
        $close = Q::ifset($column, 'close', $i > 0);
        $Q_close = Q_Request::isMobile() ? 'Q_close' : 'Q_close Q_back';
        $closeHtml = !$close ? '' : (Q_Request::isMobile() ? '<div class="Q_close Q_back">' . Q_Html::img($backSrc, 'Back') . '</div>' : '<div class="Q_close">' . Q_Html::img($closeSrc, 'Close') . '</div>');
        $n = Q_Html::text($name);
        $columnClass = 'Q_column_' . Q_Utils::normalize($name) . ' Q_column_' . $i;
        if (isset($column['html'])) {
            $html = $column['html'];
            $columns[] = <<<EOT
\t<div class="Q_columns_column {$columnClass}" data-index="{$i}" data-name="{$n}">
\t\t{$html}
\t</div>
EOT;
        } else {
            $titleHtml = Q::ifset($column, 'title', '[title]');
            $columnHtml = Q::ifset($column, 'column', '[column]');
            $classes = $columnClass . ' ' . Q::ifset($column, 'class', '');
            $attrs = '';
            if (isset($column['data'])) {
                $json = Q::json_encode($column['data']);
                $attrs = 'data-more="' . Q_Html::text($json) . '"';
                foreach ($column['data'] as $k => $v) {
                    $attrs .= 'data-' . Q_Html::text($k) . '="' . Q_Html::text($v) . '" ';
                }
            }
            $data = Q::ifset($column, 'data', '');
            $columns[] = <<<EOT
\t<div class="Q_columns_column {$classes}" data-index="{$i}" data-name="{$n}" {$attrs}>
\t\t<div class="Q_columns_title">
\t\t\t{$closeHtml}
\t\t\t<h2 class="Q_title_slot">{$titleHtml}</h2>
\t\t</div>
\t\t<div class="Q_column_slot">{$columnHtml}</div>
\t</div>
EOT;
        }
        ++$i;
    }
    $result .= "\n" . implode("\n", $columns) . "\n</div>";
    return $result;
}
Esempio n. 8
0
function Platform_api_response()
{
    $result = array();
    if ($_REQUEST['discover']) {
        $discover = $_REQUEST['discover'];
        if (is_string($discover)) {
            $discover = explode(',', $_REQUEST['discover']);
        }
        $discover = array_flip($discover);
        if (isset($discover['user'])) {
            $result['user'] = '******';
        }
        if (isset($discover['contacts'])) {
            $result['contacts'] = array('bhbsneuc' => array('labels' => array(1, 4)), 'bgeoekat' => array('labels' => array(1, 7)));
        }
    }
    $json = Q::json_encode($result);
    $referer = $_SERVER['HTTP_REFERER'];
    $parts = parse_url($referer);
    $origin = Q::json_encode($parts['scheme'] . '://' . $parts['host']);
    $appUrl = Q::json_encode(Q_Request::baseUrl());
    echo <<<EOT
<!doctype html>
<html>
    <head>
        <title>Qbix Platform</title>
\t\t<script type="text/javascript">
\t\twindow.addEventListener("message", receiveMessage, false);
\t\tfunction receiveMessage(event) {
\t\t\tvar request = event.data;
\t\t\tvar response = '';
\t\t\tif (!request.method) {
\t\t\t\tresponse = {"error": "Missing method"};
\t\t\t}
\t\t\tif (request.appUrl.substr(0, event.origin.length) !== event.origin) {
\t\t\t\tresponse = {"error": "Origin doesn't match"};
\t\t\t} else {
\t\t\t\tresponse = {$json};
\t\t\t}
\t\t\twindow.parent.postMessage(response, {$origin});
\t\t}
\t\tvar ExposedMethods = function () {
\t
\t\t};
\t\t</script>
    </head>
    <body>
    </body>
</html>
EOT;
    return false;
}
Esempio n. 9
0
/**
 * Generates a form with inputs that modify various streams
 * @class Streams form
 * @constructor
 * @param {array} $options
 *  An associative array of parameters, containing:
 * @param {array} [$options.fields] an associative array of $id => $fieldinfo pairs,
 *   where $id is the id to append to the tool's id, to generate the input's id,
 *   and fieldinfo is either an associative array with the following fields,
 *   or a regular array consisting of fields in the following order:
 *     "publisherId" => Required. The id of the user publishing the stream
 *     "streamName" => Required. The name of the stream
 *     "field" => The stream field to edit, or "attribute:$attributeName" for an attribute.
 *     "input" => The type of the input (@see Q_Html::smartTag())
 *     "attributes" => Additional attributes for the input
 *     "options" => options for the input (if type is "select", "checkboxes" or "radios")
 *     "params" => array of extra parameters to Q_Html::smartTag
 */
function Streams_form_tool($options)
{
    $fields = Q::ifset($options, 'fields', array());
    $defaults = array('publisherId' => null, 'streamName' => null, 'field' => null, 'type' => 'text', 'attributes' => array(), 'value' => array(), 'options' => array(), 'params' => array());
    $sections = array();
    $hidden = array();
    $contents = '';
    foreach ($fields as $id => $field) {
        if (Q::isAssociative($field)) {
            $r = Q::take($field, $defaults);
        } else {
            $c = count($field);
            if ($c < 4) {
                throw new Q_Exception("Streams/form tool: field needs at least 4 values");
            }
            $r = array('publisherId' => $field[0], 'streamName' => $field[1], 'field' => $field[2], 'type' => $field[3], 'attributes' => isset($field[4]) ? $field[4] : array(), 'value' => isset($field[5]) ? $field[5] : '', 'options' => isset($field[6]) ? $field[6] : null, 'params' => isset($field[7]) ? $field[7] : null);
        }
        $r['attributes']['name'] = "input_{$id}";
        if (!isset($r['type'])) {
            var_dump($r['type']);
            exit;
        }
        $stream = Streams::fetchOne(null, $r['publisherId'], $r['streamName']);
        if ($stream) {
            if (substr($r['field'], 0, 10) === 'attribute:') {
                $attribute = trim(substr($r['field'], 10));
                $value = $stream->get($attribute, $r['value']);
            } else {
                $field = $r['field'];
                $value = $stream->{$field};
            }
        } else {
            $value = $r['value'];
        }
        $tag = Q_Html::smartTag($r['type'], $r['attributes'], $value, $r['options'], $r['params']);
        $class1 = 'publisherId_' . Q_Utils::normalize($r['publisherId']);
        $class2 = 'streamName_' . Q_Utils::normalize($r['streamName']);
        $contents .= "<span class='Q_before {$class1} {$class2}'></span>" . Q_Html::tag('span', array('data-publisherId' => $r['publisherId'], 'data-streamName' => $r['streamName'], 'data-field' => $r['field'], 'data-type' => $r['type'], 'class' => "{$class1} {$class2}"), $tag);
        $hidden[$id] = array(!!$stream, $r['publisherId'], $r['streamName'], $r['field']);
    }
    $contents .= Q_Html::hidden(array('inputs' => Q::json_encode($hidden)));
    return Q_Html::form('Streams/form', 'post', array(), $contents);
    //
    // $fields = array('onSubmit', 'onResponse', 'onSuccess', 'slotsToRequest', 'loader', 'contentElements');
    // Q_Response::setToolOptions(Q::take($options, $fields));
    // Q_Response::addScript('plugins/Q/js/tools/form.js');
    // Q_Response::addStylesheet('plugins/Q/css/form.css');
    // return $result;
}
Esempio n. 10
0
function Q_scripts_combine()
{
    $environment = Q_Config::get('Q', 'environment', false);
    if (!$environment) {
        return "Config field 'Q'/'environment' is empty";
    }
    $files = Q_Config::get('Q', 'environments', $environment, 'files', Q_Config::get('Q', 'environments', '*', 'files', false));
    if (empty($files)) {
        return "Config field 'Q'/'environments'/'{$environment}'/files is empty";
    }
    $filters = Q_Config::get('Q', 'environments', $environment, 'filters', Q_Config::get('Q', 'environments', '*', 'filters', false));
    if (empty($filters)) {
        return "Config field 'Q'/'environments'/'{$environment}'/filters is empty";
    }
    $combined = array();
    foreach ($files as $src => $dest) {
        $f = Q_Uri::filenameFromUrl(Q_Html::themedUrl($src, true));
        if (!file_exists($f)) {
            return "Aborting: File corresponding to {$src} doesn't exist";
        }
        $content = file_get_contents($f);
        $combined[$dest][$src] = $content;
    }
    foreach ($combined as $dest => $parts) {
        $df = Q_Uri::filenameFromUrl(Q_Html::themedUrl($dest));
        $ext = pathinfo($df, PATHINFO_EXTENSION);
        echo "Writing {$df}\n";
        if (!empty($filters)) {
            foreach ($filters as $e => $filter) {
                if ($ext !== $e) {
                    continue;
                }
                $p = !empty($filter['params']) ? Q::json_encode($filter['params']) : '';
                echo "\t" . $filter['handler'] . "{$p}\n";
                foreach ($parts as $src => $part) {
                    echo "\t\t{$src}\n";
                }
                $params = compact('dest', 'parts');
                if (!empty($filter['params'])) {
                    $params = array_merge($params, $filter['params']);
                }
                $content = Q::event($filter['handler'], $params);
            }
        }
        file_put_contents($df, $content);
    }
    echo "Success.";
}
Esempio n. 11
0
function Q_after_Q_tool_render($params, &$result)
{
    $info = $params['info'];
    $extra = $params['extra'];
    if (!is_array($extra)) {
        $extra = array();
    }
    $id_prefix = Q_Html::getIdPrefix();
    $tool_ids = Q_Html::getToolIds();
    $tag = Q::ifset($extra, 'tag', 'div');
    if (empty($tag)) {
        Q_Html::popIdPrefix();
        return;
    }
    $classes = '';
    $data_options = '';
    $count = count($info);
    foreach ($info as $name => $opt) {
        $classes = ($classes ? "{$classes} " : $classes) . implode('_', explode('/', $name)) . '_tool';
        $options = Q_Response::getToolOptions($name);
        if (isset($options)) {
            $friendly_options = str_replace(array('&quot;', '\\/'), array('"', '/'), Q_Html::text(Q::json_encode($options)));
        } else {
            $friendly_options = '';
        }
        $normalized = Q_Utils::normalize($name, '-');
        if (isset($options) or $count > 1) {
            $id = $tool_ids[$name];
            $id_string = $count > 1 ? "{$id} " : '';
            $data_options .= " data-{$normalized}='{$id_string}{$friendly_options}'";
        }
        $names[] = $name;
    }
    if (isset($extra['classes'])) {
        $classes .= ' ' . $extra['classes'];
    }
    $attributes = isset($extra['attributes']) ? ' ' . Q_Html::attributes($extra['attributes']) : '';
    $data_retain = !empty($extra['retain']) || Q_Response::shouldRetainTool($id_prefix) ? " data-Q-retain=''" : '';
    $data_replace = !empty($extra['replace']) || Q_Response::shouldReplaceWithTool($id_prefix) ? " data-Q-replace=''" : '';
    $names = $count === 1 ? ' ' . key($info) : 's ' . implode(" ", $names);
    $ajax = Q_Request::isAjax();
    $result = "<{$tag} id='{$id_prefix}tool' " . "class='Q_tool {$classes}'{$data_options}{$data_retain}{$data_replace}{$attributes}>" . "{$result}</{$tag}>";
    if (!Q_Request::isAjax()) {
        $result = "<!--\nbegin tool{$names}\n-->{$result}<!--\nend tool{$names} \n-->";
    }
    Q_Html::popIdPrefix();
}
Esempio n. 12
0
function Streams_interests_response()
{
    // serve a javascript file and tell client to cache it
    $communityId = Q::ifset($_REQUEST, 'communityId', Users::communityId());
    $interests = Streams::interests($communityId);
    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($interests, true);
    echo "Q.setObject(['Q', 'Streams', 'Interests', 'all', '{$communityId}'], {$json});";
    return false;
}
function Streams_after_Streams_message_Streams_unrelatedTo($params)
{
    $message = $params['message'];
    $type = $message->getInstruction('type', null);
    $stream = $params['stream'];
    $rtypes = Q_Config::get('Streams', 'categorize', 'relationTypes', array());
    $stypes = Q_Config::get('Streams', 'categorize', 'streamTypes', array());
    if (!in_array($type, $rtypes) or !in_array($stream->type, $stypes)) {
        return;
    }
    $c = new Streams_Category();
    $c->publisherId = $stream->publisherId;
    $c->streamName = $stream->name;
    $fromPublisherId = $message->getInstruction('fromPublisherId', null);
    $fromStreamName = $message->getInstruction('fromStreamName', null);
    if (!isset($fromPublisherId) or !isset($fromStreamName)) {
        return;
    }
    // Begin database transaction
    $relatedTo = $c->retrieve(null, array('ignoreCache' => true, 'begin' => true)) ? json_decode($c->relatedTo, true) : array();
    if (isset($relatedTo[$type])) {
        foreach ($relatedTo[$type] as $weight => $info) {
            if ($info[0] === $fromPublisherId and $info[1] === $fromStreamName) {
                unset($relatedTo[$type][$weight]);
                break;
            }
        }
        $o = $message->getInstruction('options', null);
        $w = $message->getInstruction('weight', null);
        if (!empty($o['adjustWeights'])) {
            $rt = array();
            foreach ($relatedTo[$type] as $weight => $info) {
                if ($weight > $w) {
                    $rt[$weight - 1] = $info;
                } else {
                    $rt[$weight] = $info;
                }
            }
            $relatedTo[$type] = $rt;
        }
    }
    $c->relatedTo = Q::json_encode($relatedTo);
    $c->save();
    // End database transaction
}
Esempio n. 14
0
function Users_before_Q_session_save($params)
{
    if (empty($params['row'])) {
        return;
    }
    $row = $params['row'];
    $user = Users::loggedInUser(false, false);
    $userId = $user ? $user->id : null;
    if (Q::ifset($row, 'userId', null) !== $userId) {
        $row->userId = $userId;
    }
    $row->content = isset($_SESSION) ? Q::json_encode($_SESSION, JSON_FORCE_OBJECT) : "{}";
    if (empty($params['inserting'])) {
        return;
    }
    $row->deviceId = "";
    $row->timeout = 0;
}
function Streams_after_Streams_message_Streams_updateRelateTo($params)
{
    $message = $params['message'];
    $type = $message->getInstruction('type', null);
    $stream = $params['stream'];
    $rtypes = Q_Config::get('Streams', 'categorize', 'relationTypes', array());
    $stypes = Q_Config::get('Streams', 'categorize', 'streamTypes', array());
    if (!in_array($type, $rtypes) or !in_array($stream->type, $stypes)) {
        return;
    }
    $c = new Streams_Category();
    $c->publisherId = $stream->publisherId;
    $c->streamName = $stream->name;
    $fromPublisherId = $message->getInstruction('fromPublisherId', null);
    $fromStreamName = $message->getInstruction('fromStreamName', null);
    if (!isset($fromPublisherId) or !isset($fromStreamName)) {
        return;
    }
    // Begin database transaction
    $relatedTo = $c->retrieve(null, array('ignoreCache' => true, 'begin' => true)) ? json_decode($c->relatedTo, true) : array();
    $weight = (double) $message->getInstruction('weight', null);
    $previousWeight = (double) $message->getInstruction('previousWeight', null);
    $adjustWeightsBy = $message->getInstruction('adjustWeightsBy', null);
    if (isset($relatedTo[$type])) {
        $prev = $relatedTo[$type][$previousWeight];
        $rt = array();
        foreach ($relatedTo[$type] as $w => $info) {
            if ($weight < $previousWeight and ($w < $weight or $previousWeight <= $w)) {
                $rt[$w] = $info;
            } else {
                if ($weight >= $previousWeight and ($w <= $previousWeight or $weight < $w)) {
                    $rt[$w] = $info;
                } else {
                    $rt[$w + $adjustWeightsBy] = $info;
                }
            }
        }
        $rt[$weight] = $prev;
        $relatedTo[$type] = $rt;
    }
    $c->relatedTo = Q::json_encode($relatedTo);
    $c->save();
    // End database transaction
}
Esempio n. 16
0
function Users_after_Q_session_write($params)
{
    Q::$state['session'] = true;
    if (!$params['changed']) {
        return;
    }
    // Q::autoload('Db');
    // Q::autoload('Db_Mysql');
    // Q::autoload('Db_Result');
    // Q::autoload('Db_Expression');
    // Q::autoload('Db_Query');
    // Q::autoload('Db_Query_Mysql');
    // Q::autoload('Db_Row');
    // Q::autoload('Base_Users_Session');
    // Q::autoload('Base_Users');
    // Q::autoload('Users');
    Q::autoload('Q_Utils');
    Q::autoload('Q_Config');
    Q::autoload('Q_Session');
    $id = Q_Session::id();
    if (!$id) {
        return;
    }
    $parts = explode('-', $id);
    $duration = count($parts) > 1 ? $parts[0] : 0;
    $content = Q::json_encode($_SESSION, JSON_FORCE_OBJECT);
    if (Users::$loggedOut) {
        Q_Utils::sendToNode(array("Q/method" => "Users/session", "sessionId" => $id, "content" => null, "duration" => $duration));
    } else {
        if (Q_Session::id() and !empty($_SERVER['HTTP_HOST'])) {
            try {
                Q_Utils::sendToNode(array("Q/method" => "Users/session", "sessionId" => $id, "content" => $content, "duration" => $duration));
            } catch (Exception $e) {
                // don't throw here, it would only result in a mysterious fatal error
            }
        }
    }
}
function Streams_after_Streams_message_Streams_relatedTo($params)
{
    $message = $params['message'];
    $type = $message->getInstruction('type', null);
    $stream = $params['stream'];
    $rtypes = Q_Config::get('Streams', 'categorize', 'relationTypes', array());
    $stypes = Q_Config::get('Streams', 'categorize', 'streamTypes', array());
    if (!in_array($type, $rtypes) or !in_array($stream->type, $stypes)) {
        return;
    }
    $c = new Streams_Category();
    $c->publisherId = $stream->publisherId;
    $c->streamName = $stream->name;
    $fromPublisherId = $message->getInstruction('fromPublisherId', null);
    $fromStreamName = $message->getInstruction('fromStreamName', null);
    if (!isset($fromPublisherId) or !isset($fromStreamName)) {
        return;
    }
    // Begin database transaction
    $relatedTo = $c->retrieve(null, array('ignoreCache' => true, 'begin' => true)) ? json_decode($c->relatedTo, true) : array();
    $weight = (double) $message->getInstruction('weight', null);
    if (!isset($weight)) {
        $rt = new Streams_RelatedTo();
        $rt->toPublisherId = $stream->publisherId;
        $rt->toStreamName = $stream->name;
        $rt->type = $type;
        $rt->fromPublisherId = $fromPublisherId;
        $rt->fromStreamName = $fromStreamName;
        $rt->retrieve(null, null, array('ignoreCache' => true));
        $weight = $rt->weight;
    }
    $fs = Streams::fetchOne($message->byUserId, $fromPublisherId, $fromStreamName);
    $weight = floor($weight);
    $relatedTo[$type][$weight] = array($fromPublisherId, $fromStreamName, $fs->title, $fs->icon);
    $c->relatedTo = Q::json_encode($relatedTo);
    $c->save(false, true);
    // End database transaction
}
Esempio n. 18
0
function Users_after_Q_session_destroy($params)
{
    Q::$state['session'] = true;
    //  Q::autoload('Db');
    //  Q::autoload('Db_Mysql');
    //  Q::autoload('Db_Result');
    //  Q::autoload('Db_Expression');
    //  Q::autoload('Db_Query');
    //  Q::autoload('Db_Query_Mysql');
    //  Q::autoload('Db_Row');
    //  Q::autoload('Base_Users_Session');
    //  Q::autoload('Base_Users');
    //  Q::autoload('Users');
    Q::autoload('Q_Utils');
    Q::autoload('Q_Config');
    Q::autoload('Q_Session');
    $id = Q_Session::id();
    if (!$id) {
        return;
    }
    $content = Q::json_encode($_SESSION, JSON_FORCE_OBJECT);
    Q_Utils::sendToNode(array("Q/method" => "Users/session", "sessionId" => $id, "content" => null, "updatedTime" => null, "destroyed" => true));
}
Esempio n. 19
0
 /**
  * Adds a link to someone who is not yet a user
  * @method addLink
  * @static
  * @param {string} $address Could be email address, mobile number, etc.
  * @param {string} [$type=null] One of 'email', 'mobile', 'email_hashed', 'mobile_hashed', 'facebook', or 'twitter' for now.
  * If not indicated, the function tries to guess by using Q_Valid functions.
  * @param {array} [$extraInfo=array()] Associative array of information you have imported
  * from the address book. Should contain at least the keys:
  *
  * * "firstName" => the imported first name
  * * "lastName" => the imported last name
  * * "labels" => array of the imported names of the contact groups to add this user to once they sign up
  *
  * @return {boolean|integer} Returns true if the link row was created
  * Or returns a string $userId if user already exists and has verified this address.
  * @throws {Q_Exception_WrongValue} If $address is not a valid id
  * @throws {Users_Exception_NotLoggedIn} If user is not logged in
  */
 static function addLink($address, $type = null, $extraInfo = array())
 {
     // process the address first
     $address = trim($address);
     $ui_type = $type;
     switch ($type) {
         case 'email':
             if (!Q_Valid::email($address, $normalized)) {
                 throw new Q_Exception_WrongValue(array('field' => 'address', 'range' => 'email address'));
             }
             $ui_type = 'email_hashed';
             $ui_value = 'email_hashed:' . Q_Utils::hash($normalized);
             break;
         case 'email_hashed':
             // Assume that the $address was already hashed in the standard way
             // see Q_Utils::hash
             $ui_value = "email_hashed:{$address}";
             break;
         case 'mobile':
             if (!isset($options['hashed']) and !Q_Valid::phone($address, $normalized)) {
                 throw new Q_Exception_WrongValue(array('field' => 'address', 'range' => 'phone number'));
             }
             $ui_type = 'mobile_hashed';
             $ui_value = 'mobile_hashed:' . Q_Utils::hash($normalized);
             break;
         case 'mobile_hashed':
             // Assume that the $address was already hashed in the standard way
             // see Q_Utils::hash
             $ui_value = "mobile_hashed:{$address}";
             break;
         case 'facebook':
             if (!isset($options['hashed']) and !is_numeric($address)) {
                 throw new Q_Exception_WrongValue(array('field' => 'address', 'range' => 'facebook uid'));
             }
             $ui_value = "facebook:{$address}";
             $normalized = $address;
             break;
         case 'twitter':
             if (!isset($options['hashed']) and !is_numeric($address)) {
                 throw new Q_Exception_WrongValue(array('field' => 'address', 'range' => 'twitter uid'));
             }
             $ui_value = "twitter:{$address}";
             $normalized = $address;
             break;
         default:
             if (Q_Valid::email($address, $normalized)) {
                 $ui_type = 'email_hashed';
                 $ui_value = 'email_hashed:' . Q_Utils::hash($normalized);
             } else {
                 if (Q_Valid::phone($address, $normalized)) {
                     $ui_type = 'mobile_hashed';
                     $ui_value = 'mobile_hashed:' . Q_Utils::hash($normalized);
                 } else {
                     throw new Q_Exception_WrongValue(array('field' => 'type', 'range' => 'one of email, mobile, email_hashed, mobile_hashed, facebook, twitter'));
                 }
             }
             break;
     }
     $user = Users::loggedInUser(true);
     // Check if the contact user already exists, and if so, add a contact instead of a link
     $ui = Users::identify($ui_type, $ui_value);
     if ($ui) {
         // Add a contact instead of a link
         $user->addContact($ui->userId, Q::ifset($extraInfo, 'labels', null));
         return $user->id;
     }
     // Add a link if one isn't already there
     $link = new Users_Link();
     $link->identifier = $ui_value;
     $link->userId = $user->id;
     if ($link->retrieve()) {
         return false;
     }
     $link->extraInfo = Q::json_encode($extraInfo);
     $link->save();
     return true;
 }
Esempio n. 20
0
function Q_exception_native($params)
{
    extract($params);
    /**
     * @var Exception $exception 
     */
    if ($is_ajax = Q_Request::isAjax()) {
        $json = @Q::json_encode(array('errors' => Q_Exception::toArray(array($exception))));
        $callback = Q_Request::callback();
        switch (strtolower($is_ajax)) {
            case 'iframe':
                // Render an HTML layout for ajax
                if (!Q_Response::$batch) {
                    header("Content-type: text/html");
                }
                echo <<<EOT
<!doctype html><html lang=en>
<head><meta charset=utf-8><title>Q Result</title></head>
<body>
<script type="text/javascript">
window.result = function () { return {$json} };
</script>
</body>
</html>
EOT;
                break;
            case 'json':
                // Render a JSON layout for ajax
            // Render a JSON layout for ajax
            default:
                header("Content-type: " . ($callback ? "application/javascript" : "application/json"));
                echo $callback ? "{$callback}({$json})" : $json;
        }
    } else {
        if (Q::textMode()) {
            echo Q_Exception::coloredString($exception);
            exit;
        }
        $message = $exception->getMessage();
        $file = $exception->getFile();
        $line = $exception->getLine();
        if (is_callable(array($exception, 'getTraceAsStringEx'))) {
            $trace_string = $exception->getTraceAsStringEx();
        } else {
            $trace_string = $exception->getTraceAsString();
        }
        if ($exception instanceof Q_Exception_PhpError or !empty($exception->messageIsHtml)) {
            // do not sanitize $message
        } else {
            $message = Q_Html::text($message);
        }
        $content = "<h1 class='exception_message'>{$message}</h1>";
        if (Q_Config::get('Q', 'exception', 'showFileAndLine', true)) {
            $content .= "<h3 class='exception_fileAndLine'>in {$file} ({$line})</h3>";
        }
        if (Q_Config::get('Q', 'exception', 'showTrace', true)) {
            $content .= "<pre class='exception_trace'>{$trace_string}</pre>";
        }
        $content .= str_repeat(' ', 512);
        // because of chrome
        $title = "Exception occurred";
        $dashboard = "";
        echo Q::view('Q/layout/html.php', compact('content', 'dashboard', 'title'));
    }
    $app = Q_Config::get('Q', 'app', null);
    $colored = Q_Exception::coloredString($exception);
    Q::log("{$app}: Exception in " . ceil(Q::milliseconds()) . "ms:\n\n{$colored}\n", null, true, array('maxLength' => 10000));
}
Esempio n. 21
0
 /**
  * Starts a recurring subscription
  * @param {Streams_Stream} $plan The subscription plan stream
  * @param {string} [$payments=null] The type of payments processor, could be "authnet" or "stripe". If omitted, the subscription proceeds without any payments.
  * @param {array} [$options=array()] Options for the subscription
  * @param {date} [$options.startDate=today] The start date of the subscription
  * @param {date} [$options.endDate=today+year] The end date of the subscription
  * @param {Users_User} [$options.user=Users::loggedInUser()] Allows us to set the user to subscribe
  * @param {Users_User} [$options.publisherId=Users::communityId()] Allows us to override the publisher to subscribe to
  * @param {string} [$options.description=null] description of the charge, to be sent to customer
  * @param {string} [$options.metadata=null] any additional metadata to store with the charge
  * @param {string} [$options.subscription=null] if this charge is related to a subscription stream
  * @param {string} [$options.subscription.publisherId]
  * @param {string} [$options.subscription.streamName]
  * @throws Assets_Exception_DuplicateTransaction
  * @throws Assets_Exception_HeldForReview
  * @throws Assets_Exception_ChargeFailed
  * @return {Streams_Stream} A stream of type 'Assets/subscription' representing this subscription
  */
 static function startSubscription($plan, $payments = null, $options = array())
 {
     if (!isset($options['user'])) {
         $options['user'] = Users::loggedInUser(true);
     }
     $app = Q_Config::expect('Q', 'app');
     $user = Q::ifset($options, 'user', Users::loggedInUser(true));
     $currency = 'USD';
     // TODO: may want to implement support for currency conversion
     $startDate = Q::ifset($options, 'startDate', date("Y-m-d"));
     $startDate = date('Y-m-d', strtotime($startDate));
     $months = $plan->getAttribute('months', 12);
     $amount = $plan->getAttribute('amount');
     $endDate = date("Y-m-d", strtotime("-1 day", strtotime("+{$months} month", strtotime($startDate))));
     $endDate = date('Y-m-d', strtotime($endDate));
     $publisherId = Q::ifset($options, 'publisherId', Users::communityId());
     $publisher = Users_User::fetch($publisherId);
     $streamName = "Assets/subscription/{$user->id}/{$plan->name}";
     if ($subscription = Streams::fetchOne($publisherId, $publisherId, $streamName)) {
         return $subscription;
         // it already started
     }
     $attributes = Q::json_encode(array('payments' => $payments, 'planPublisherId' => $plan->publisherId, 'planStreamName' => $plan->name, 'startDate' => $startDate, 'endDate' => $endDate, 'months' => $months, 'amount' => $amount, 'currency' => $currency));
     $stream = Streams::create($publisherId, $publisherId, "Assets/subscription", array('name' => $streamName, 'title' => $plan->title, 'readLevel' => Streams::$READ_LEVEL['none'], 'writeLevel' => Streams::$WRITE_LEVEL['none'], 'adminLevel' => Streams::$ADMIN_LEVEL['none'], 'attributes' => $attributes));
     $access = new Streams_Access(array('publisherId' => $publisherId, 'streamName' => $streamName, 'ofUserId' => $user->id, 'grantedByUserId' => $app, 'readLevel' => Streams::$READ_LEVEL['max'], 'writeLevel' => -1, 'adminLevel' => -1));
     $access->save();
     $amount = $plan->getAttribute('amount', null);
     if (!is_numeric($amount)) {
         throw new Q_Exception_WrongValue(array('field' => 'amount', 'range' => 'an integer'));
     }
     $options['stream'] = $stream;
     if ($payments) {
         Assets::charge($payments, $amount, $currency, $options);
     }
     /**
      * @event Assets/startSubscription {before}
      * @param {Streams_Stream} plan
      * @param {Streams_Stream} subscription
      * @param {string} startDate
      * @param {string} endDate
      * @return {Users_User}
      */
     Q::event('Assets/startSubscription', compact('plan', 'user', 'publisher', 'stream', 'startDate', 'endDate', 'months', 'currency'), 'after');
     return $stream;
 }
Esempio n. 22
0
 /**
  * Saves parameters to a file
  * @method save
  * @param {string} $filename Name of file to save to. If tree was loaded, you can leave this blank to update that file.
  * @param {array} [$array_path=array()] Array of keys identifying the path of the config subtree to save
  * @return {boolean} Returns true if saved, otherwise false;
  **/
 function save($filename = null, $array_path = array(), $prefix_path = null)
 {
     if (empty($filename) and !empty($this->filename)) {
         $filename = $this->filename;
     }
     if (!($filename2 = Q::realPath($filename))) {
         $filename2 = $filename;
     }
     if (empty($array_path)) {
         $array_path = array();
         $toSave = $this->parameters;
     } else {
         $array_path[] = null;
         $toSave = call_user_func_array(array($this, 'get'), $array_path);
     }
     if (is_null($prefix_path)) {
         $prefix_path = $array_path;
     }
     $prefix_path = array_reverse($prefix_path);
     foreach ($prefix_path as $ap) {
         if ($ap) {
             $toSave = array($ap => $toSave);
         }
     }
     $mask = umask(Q_Config::get('Q', 'internal', 'umask', 00));
     $success = file_put_contents($filename2, !empty($toSave) ? Q::json_encode($toSave, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) : '{}', LOCK_EX);
     clearstatcache(true, $filename2);
     umask($mask);
     if ($success) {
         self::$cache[$filename] = $toSave;
         Q_Cache::set("Q_Tree\t{$filename}", $toSave);
         // no need to check result - on failure Q_Cache is disabled
     }
     return $success;
 }
Esempio n. 23
0
 /**
  * Unsubcsribe from all or specific stream's messages
  * @method unsubscribe
  * @param $options=array() {array}
  *  "userId": The user who is unsubscribing from the stream. Defaults to the logged-in user.
  *  "skipAccess": if true, skip access check for whether user can unsubscribe
  * @return {boolean}
  */
 function unsubscribe($options = array())
 {
     $stream = $this->fetchAsUser($options, $userId);
     if (empty($options['skipAccess']) and !$stream->testReadLevel('messages')) {
         if (!$stream->testReadLevel('see')) {
             throw new Streams_Exception_NoSuchStream();
         }
         throw new Users_Exception_NotAuthorized();
     }
     $participant = $stream->join(array("userId" => $userId, 'subscribed' => false, 'noVisit' => true, "skipAccess" => Q::ifset($options, 'skipAccess', false)));
     Q_Utils::sendToNode(array("Q/method" => "Streams/Stream/unsubscribe", "stream" => Q::json_encode($stream->toArray()), "participant" => Q::json_encode($participant), "success" => Q::json_encode(!!$participant)));
     // Post Streams/unsubscribe message to the stream
     $stream->post($userId, array('type' => 'Streams/unsubscribe'), true);
     // Now post Streams/unsubscribed message to Streams/participating
     Streams_Message::post($userId, $userId, 'Streams/participating', array('type' => 'Streams/unsubscribed', 'instructions' => Q::json_encode(array('publisherId' => $stream->publisherId, 'streamName' => $stream->name))), true);
     return !!$participant;
 }
Esempio n. 24
0
<?php

echo Q::json_encode(compact(Q_Response::getRequestedSlots()));
Esempio n. 25
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'));
}
Esempio n. 26
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();
    }
}
Esempio n. 27
0
 /**
  * Validates the request sent by the javascript
  * @method validateRequest
  * @static
  */
 static function validateRequest()
 {
     if (empty($_REQUEST['url'])) {
         self::respond(Q::json_encode(array('errors' => 'url is missing')));
         exit;
     }
 }
Esempio n. 28
0
 function clearInstruction($instructionName)
 {
     $instr = $this->getAllInstructions();
     unset($instr[$instructionName]);
     $this->instructions = Q::json_encode($instr);
 }
Esempio n. 29
0
 /**
  * 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'));
     }
     $instructions_json = Q::json_encode(array_merge(array('app' => Q_Config::expect('Q', 'app')), $more));
     $from_stream = self::userStream(null, null, true);
     $existing_amount = $from_stream->getAttribute('amount');
     if ($existing_amount < $amount) {
         throw new Awards_Exception_NotEnoughCredits(array('missing' => $amount - $existing_amount));
     }
     $from_stream->setAttribute('amount', $from_stream->getAttribute('amount') - $amount);
     $from_stream->save();
     $from_stream->post($user->id, array('type' => 'Awards/credits/sent', 'content' => $amount, 'instructions' => $instructions_json));
     // TODO: add journaling system
     // Because if the following fails, then someone will lose credits
     // without the other person getting them. For now we will rely on the user complaining.
     $to_stream = self::userStream($toUserId, $toUserId, true);
     $to_stream->setAttribute('amount', $to_stream->getAttribute('amount') + $amount);
     $to_stream->save();
     $to_stream->post($user->id, array('type' => 'Awards/credits/received', 'content' => $amount, 'instructions' => $instructions_json));
 }
Esempio n. 30
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);
 }