Пример #1
0
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);
}
Пример #2
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());
}
function Streams_0_8_4_Streams_mysql()
{
    $app = Q_Config::expect('Q', 'app');
    $communityId = Users::communityId();
    $user = Users_User::fetch($communityId);
    // avatar for the App user
    $avatar = new Streams_Avatar();
    $avatar->toUserId = $communityId;
    $avatar->publisherId = $communityId;
    $avatar->username = $user->username;
    $avatar->firstName = Users::communityName();
    $avatar->lastName = Users::communitySuffix();
    $avatar->icon = $user->icon;
    $avatar->save();
    $avatar2 = new Streams_Avatar();
    $avatar2->copyFrom($avatar, null, false, true);
    $avatar->toUserId = '';
    $avatar->save();
    // access stream for managing app roles
    $stream = new Streams_Stream();
    $stream->publisherId = Users::communityId();
    $stream->name = 'Streams/contacts';
    $stream->type = 'Streams/resource';
    $stream->title = "Contacts";
    $stream->setAttribute('prefixes', array("Users/", "{$app}/"));
    $stream->save();
    // access stream for managing app roles
    $stream = new Streams_Stream();
    $stream->publisherId = $app;
    $stream->name = 'Streams/labels';
    $stream->type = 'Streams/resource';
    $stream->title = "Labels";
    $stream->setAttribute('prefixes', array("Users/", "{$app}/"));
    $stream->save();
    // access for managing app contacts
    $access = new Streams_Access();
    $access->publisherId = $communityId;
    $access->streamName = 'Streams/contacts';
    $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 app roles
    $access = new Streams_Access();
    $access->publisherId = $communityId;
    $access->streamName = 'Streams/labels';
    $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();
}
Пример #4
0
 /**
  * Create award stream for logged-in user
  * @method createStream
  * @static
  * @param {Users_User} $user The user for which stream is created
  * @return {Streams_Stream}
  */
 static function createStream($user)
 {
     $stream = new Streams_Stream();
     $stream->publisherId = $user->id;
     $stream->name = 'Awards/credits';
     $stream->type = 'Awards/credits';
     $stream->icon = 'plugins/Awards/img/credits.png';
     $app = Q_Config::expect('Q', 'app');
     $stream->title = 'Credits';
     $stream->content = '';
     $stream->setAttribute('amount', Q_Config::get('Awards', 'credits', 'amounts', 'Users/insertUser', 20));
     $stream->save();
     return $stream;
 }
Пример #5
0
function Broadcast_main_response_content()
{
    Q_Response::addScript('plugins/Broadcast/js/Broadcast.js');
    $user = Users::loggedInUser(true);
    $stream = new Streams_Stream();
    $stream->publisherId = $user->id;
    $stream->name = 'Broadcast/main';
    if (!$stream->retrieve()) {
        $stream->type = 'Broadcast';
        $stream->title = "Main broadcast stream";
        $stream->content = "Whatever you post to this stream will be syndicated by everyone who has opted in.";
        $stream->save();
    }
    Q_Response::redirect('Broadcast/stream publisherId=' . $stream->publisherId . ' name=Broadcast/main');
}
Пример #6
0
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
    Streams::create($app, $app, 'Streams/community', array('skipAccess' => true, 'name' => 'Streams/community/main', 'title' => "{$app} Community"));
    // symlink the labels folder
    if (!file_exists('Streams')) {
        Q_Utils::symlink(STREAMS_PLUGIN_FILES_DIR . DS . 'Streams' . DS . 'icons' . DS . 'labels' . DS . 'Streams', USERS_PLUGIN_FILES_DIR . DS . 'Users' . DS . 'icons' . DS . 'Streams');
    }
}
function Streams_after_Users_User_saveExecute($params)
{
    // If the username or icon was somehow modified,
    // update all the avatars for this publisher
    $modifiedFields = $params['modifiedFields'];
    $user = $params['row'];
    $updates = array();
    if (isset($modifiedFields['username'])) {
        $updates['username'] = $modifiedFields['username'];
    }
    if (isset($modifiedFields['icon'])) {
        $updates['icon'] = $modifiedFields['icon'];
    }
    if ($user->id === Users::communityId()) {
        $firstName = Users::communityName();
        $lastName = Users::communitySuffix();
        $firstName = $firstName ? $firstName : "";
        $lastName = $lastName ? $lastName : "";
    } else {
        $firstName = Q::ifset(Streams::$cache, 'register', 'first', '');
        $lastName = Q::ifset(Streams::$cache, 'register', 'last', '');
    }
    if ($params['inserted']) {
        // create some standard streams for them
        $onInsert = Q_Config::get('Streams', 'onInsert', 'Users_User', array());
        if (!$onInsert) {
            return;
        }
        $p = new Q_Tree();
        $p->load(STREAMS_PLUGIN_CONFIG_DIR . DS . 'streams.json');
        $p->load(APP_CONFIG_DIR . DS . 'streams.json');
        $values = array('Streams/user/firstName' => $firstName, 'Streams/user/lastName' => $lastName);
        // Check for user data from facebook
        if (!empty(Users::$cache['facebookUserData'])) {
            $userData = Users::$cache['facebookUserData'];
            foreach ($userData as $name_fb => $value) {
                foreach ($p->getAll() as $name => $info) {
                    if (isset($info['name_fb']) and $info['name_fb'] === $name_fb) {
                        $onInsert[] = $name;
                        $values[$name] = $value;
                    }
                }
            }
        }
        foreach ($onInsert as $name) {
            $stream = Streams::fetchOne($user->id, $user->id, $name);
            if (!$stream) {
                // it shouldn't really be in the db yet
                $stream = new Streams_Stream();
                $stream->publisherId = $user->id;
                $stream->name = $name;
            }
            $stream->type = $p->expect($name, "type");
            $stream->title = $p->expect($name, "title");
            $stream->content = $p->get($name, "content", '');
            // usually empty
            $stream->readLevel = $p->get($name, 'readLevel', Streams_Stream::$DEFAULTS['readLevel']);
            $stream->writeLevel = $p->get($name, 'writeLevel', Streams_Stream::$DEFAULTS['writeLevel']);
            $stream->adminLevel = $p->get($name, 'adminLevel', Streams_Stream::$DEFAULTS['adminLevel']);
            if ($name === "Streams/user/icon") {
                $sizes = Q_Config::expect('Users', 'icon', 'sizes');
                sort($sizes);
                $stream->setAttribute('sizes', $sizes);
                $stream->icon = $user->iconUrl();
            }
            if (isset($values[$name])) {
                $stream->content = $values[$name];
            }
            $stream->save();
            // this also inserts avatars
            $o = array('userId' => $user->id, 'skipAccess' => true);
            $so = $p->get($name, "subscribe", array());
            if ($so === false) {
                $stream->join($o);
            } else {
                $stream->subscribe(array_merge($o, $so));
            }
        }
        // Save a greeting stream, to be edited
        $communityId = Users::communityId();
        Streams::create($user->id, $user->id, "Streams/greeting", array('name' => "Streams/greeting/{$communityId}"));
        // Create some standard labels
        $label = new Users_Label();
        $label->userId = $user->id;
        $label->label = 'Streams/invited';
        $label->icon = 'labels/Streams/invited';
        $label->title = 'People I invited';
        $label->save(true);
        $label2 = new Users_Label();
        $label2->userId = $user->id;
        $label2->label = 'Streams/invitedMe';
        $label2->icon = 'labels/Streams/invitedMe';
        $label2->title = 'Who invited me';
        $label2->save(true);
        // By default, users they invite should see their full name
        $access = new Streams_Access();
        $access->publisherId = $user->id;
        $access->streamName = 'Streams/user/firstName';
        $access->ofUserId = '';
        $access->ofContactLabel = 'Streams/invited';
        $access->grantedByUserId = $user->id;
        $access->readLevel = Streams::$READ_LEVEL['content'];
        $access->writeLevel = -1;
        $access->adminLevel = -1;
        $access->save();
        $access = new Streams_Access();
        $access->publisherId = $user->id;
        $access->streamName = 'Streams/user/lastName';
        $access->ofUserId = '';
        $access->ofContactLabel = 'Streams/invited';
        $access->grantedByUserId = $user->id;
        $access->readLevel = Streams::$READ_LEVEL['content'];
        $access->writeLevel = -1;
        $access->adminLevel = -1;
        $access->save();
        // NOTE: the above saving of access caused Streams::updateAvatar to run,
        // insert a Streams_Avatar row for the new user, and properly configure it.
    } else {
        if ($modifiedFields) {
            if ($updates) {
                Streams_Avatar::update()->set($updates)->where(array('publisherId' => $user->id))->execute();
            }
            foreach ($modifiedFields as $field => $value) {
                $name = Q_Config::get('Streams', 'onUpdate', 'Users_User', $field, null);
                if (!$name) {
                    continue;
                }
                $stream = isset(Streams::$beingSaved[$field]) ? Streams::$beingSaved[$field] : Streams::fetchOne($user->id, $user->id, $name);
                if (!$stream) {
                    // it should probably already be in the db
                    continue;
                }
                $stream->content = $value;
                if ($name === "Streams/user/icon") {
                    $sizes = Q_Config::expect('Users', 'icon', 'sizes');
                    sort($sizes);
                    $attributes = $stream->attributes;
                    $stream->setAttribute('sizes', $sizes);
                    $stream->icon = $changes['icon'] = $user->iconUrl();
                }
                Streams::$beingSavedQuery = $stream->changed($user->id);
            }
        }
    }
}
Пример #8
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.
 * @param {String} [$_REQUEST.subscribe] Optional. Defauls to false. Whether to subscribe rather than just join the interest stream.
 * @return {void}
 */
function Streams_interest_post()
{
    $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) {
        $stream = Streams::create($publisherId, $publisherId, 'Streams/interest', array('name' => $name, 'title' => $title));
        $parts = explode(': ', $title, 2);
        $keywords = implode(' ', $parts);
        try {
            $data = Q_Image::pixabay($keywords, array('orientation' => 'horizontal', 'min_width' => '500', 'safesearch' => 'true', 'image_type' => 'photo'), true);
        } catch (Exception $e) {
            Q::log("Exception during Streams/interest post: " . $e->getMessage());
            $data = null;
        }
        if (!empty($data)) {
            $sizes = Q_Config::expect('Streams', 'icons', 'sizes');
            ksort($sizes);
            $params = array('data' => $data, 'path' => "plugins/Streams/img/icons", 'subpath' => $name, 'save' => $sizes, 'skipAccess' => true);
            Q_Image::save($params);
            $stream->icon = $name;
        }
        $stream->save();
    }
    $subscribe = !!Q::ifset($_REQUEST, 'subscribe', false);
    if ($subscribe) {
        if (!$stream->subscription($user->id)) {
            $stream->subscribe();
        }
    } else {
        $stream->join();
    }
    $myInterestsName = 'Streams/user/interests';
    $myInterests = Streams::fetchOne($user->id, $user->id, $myInterestsName);
    if (!$myInterests) {
        $myInterests = new Streams_Stream();
        $myInterests->publisherId = $user->id;
        $myInterests->name = $myInterestsName;
        $myInterests->type = 'Streams/category';
        $myInterests->title = 'My Interests';
        $myInterests->save();
    }
    Streams::relate($user->id, $user->id, 'Streams/user/interests', 'Streams/interest', $publisherId, $name, array('weight' => '+1'));
    Q_Response::setSlot('publisherId', $publisherId);
    Q_Response::setSlot('streamName', $name);
    /**
     * Occurs when the logged-in user has successfully added an interest via HTTP
     * @event Streams/interest/post {after}
     * @param {string} publisherId The publisher of the interest stream
     * @param {string} title The title of the interest
     * @param {boolean} subscribe Whether the user subscribed to the interest stream
     * @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/add", compact('publisherId', 'title', 'subscribe', 'user', 'stream', 'myInterests'), 'after');
}
Пример #9
0
 /**
  * Retrieve the user's stream needed to post invite messages
  * If stream does not exists - create it. May return null if save failed.
  * @method getInvitedStream
  * @static
  * @param $asUserId {string}
  *	The user id of inviting user
  * @param $forUserId {string}
  *	User id for which stream is created
  * @return {Streams_Stream|null}
  */
 static function getInvitedStream($asUserId, $forUserId)
 {
     $invited = Streams::fetch($asUserId, $forUserId, 'Streams/invited');
     if (!empty($invited)) {
         return $invited['Streams/invited'];
     }
     $invited = new Streams_Stream();
     $invited->publisherId = $forUserId;
     $invited->name = 'Streams/invited';
     $invited->type = 'Streams/invited';
     $invited->title = 'Streams/invited';
     $invited->content = 'Post message here when user is invited to some stream';
     $invited->readLevel = Streams::$READ_LEVEL['none'];
     $invited->writeLevel = Streams::$WRITE_LEVEL['post'];
     // anyone can post messages
     $invited->adminLevel = Streams::$ADMIN_LEVEL['none'];
     $result = $invited->save(true);
     //Streams::calculateAccess($asUserId, $forUserId, array('Streams/invited' => $invited), false);
     return $result ? $invited : null;
 }
Пример #10
0
 /**
  * Closes a stream, which prevents anyone from posting messages to it
  * unless they have WRITE_LEVEL >= "close", as well as attempting to remove
  * all relations to other streams. A "cron job" can later go and delete
  * closed streams. The reason you should avoid deleting streams right away
  * is that other subscribers may still want to receive the last messages
  * posted to the stream.
  * @method close
  * @param {string} $asUserId The id of the user who would be closing the stream
  * @param {string} $publisherId The id of the user publishing the stream
  * @param {string} $streamName The name of the stream
  * @param {array} [$options=array()] Can include "skipAccess"
  * @static
  */
 static function close($asUserId, $publisherId, $streamName, $options = array())
 {
     $stream = new Streams_Stream();
     $stream->publisherId = $publisherId;
     $stream->name = $streamName;
     if (!$stream->retrieve()) {
         throw new Q_Exception_MissingRow(array('table' => 'stream', 'criteria' => "{publisherId: '{$publisherId}', name: '{$streamName}'}"));
     }
     // Authorization check
     if (empty($options['skipAccess'])) {
         if ($asUserId !== $publisherId) {
             $stream->calculateAccess($asUserId);
             if (!$stream->testWriteLevel('close')) {
                 throw new Users_Exception_NotAuthorized();
             }
         }
     }
     // Clean up relations from other streams to this category
     list($relations, $related) = Streams::related($asUserId, $stream->publisherId, $stream->name, true);
     foreach ($relations as $r) {
         try {
             Streams::unrelate($asUserId, $r->fromPublisherId, $r->fromStreamName, $r->type, $stream->publisherId, $stream->name);
         } catch (Exception $e) {
         }
     }
     // Clean up relations from this stream to categories
     list($relations, $related) = Streams::related($asUserId, $stream->publisherId, $stream->name, false);
     foreach ($relations as $r) {
         try {
             Streams::unrelate($asUserId, $r->toPublisherId, $r->toStreamName, $r->type, $stream->publisherId, $stream->name);
         } catch (Exception $e) {
         }
     }
     $result = false;
     try {
         $db = $stream->db();
         $stream->closedTime = $closedTime = $db->toDateTime($db->getCurrentTimestamp());
         if ($stream->save()) {
             $stream->post($asUserId, array('type' => 'Streams/closed', 'content' => '', 'instructions' => compact('closedTime')), true);
             $result = true;
         }
     } catch (Exception $e) {
         throw $e;
     }
     return $result;
 }
Пример #11
0
 /**
  * Fetch a stream on which messages are posted relating to things happening
  * a given number of $miles around the given location.
  * If it doesn't exist, create it.
  * @method stream
  * @static
  * @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.
  * @param {string} $publisherId The id of the publisher to publish this stream
  *  Defaults to the app name in Q/app config.
  * @param {string} $streamName The name of the stream to create.
  *  Defaults to Places_Nearby::streamName($latitude, $longitude, $miles).
  * @return {Streams_Stream} Returns the stream object that was created or fetched.
  */
 static function stream($latitude, $longitude, $miles, $publisherId = null, $streamName = null)
 {
     list($latitude, $longGrid) = Places::quantize($latitude, $longitude, $miles);
     $zipcodes = Places_Zipcode::nearby($latitude, $longitude, $miles, 1);
     if (!isset($publisherId)) {
         $publisherId = Q_Config::expect('Q', 'app');
     }
     if (!isset($streamName)) {
         $streamName = self::streamName($latitude, $longitude, $miles);
     }
     if ($stream = Streams::fetchOne(null, $publisherId, $streamName)) {
         return $stream;
     }
     $zipcode = $zipcodes ? reset($zipcodes) : null;
     $stream = new Streams_Stream();
     $stream->publisherId = $publisherId;
     $stream->name = $streamName;
     $stream->type = "Places/nearby";
     $stream->title = $zipcode ? "Nearby ({$latitude}, {$longitude}): {$zipcode->placeName}, zipcode {$zipcode->zipcode}" : "Nearby ({$latitude}, {$longitude})";
     $stream->setAttribute('latitude', $latitude);
     $stream->setAttribute('longitude', $longitude);
     if ($zipcode) {
         $stream->setAttribute('zipcode', $zipcode->zipcode);
         $stream->setAttribute('placeName', $zipcode->placeName);
         $stream->setAttribute('state', $zipcode->state);
     }
     $stream->save();
     return $stream;
 }
Пример #12
0
 /**
  * Get a Places/location stream published by a publisher for a given placeId.
  * This is used to cache information from the Google Places API.
  * @method stream
  * @static
  * @param {string} $publisherId
  * @param {string} $placeId The id of the place in Google Places
  * @param {boolean} $throwIfBadValue
  *  Whether to throw Q_Exception if the result contains a bad value
  * @return {Streams_Stream|null}
  * @throws {Q_Exception} if a bad value is encountered and $throwIfBadValue is true
  */
 static function stream($publisherId, $placeId, $throwIfBadValue = false)
 {
     if (empty($placeId)) {
         if ($throwIfBadValue) {
             throw new Q_Exception_RequiredField(array('field' => 'id'));
         }
         return null;
     }
     // sanitize the ID
     $characters = '/[^A-Za-z0-9]+/';
     $result = preg_replace($characters, '_', $placeId);
     // see if it's already in the system
     $location = new Streams_Stream();
     $location->publisherId = $publisherId;
     $location->name = "Places/location/{$placeId}";
     if ($location->retrieve()) {
         $ut = $location->updatedTime;
         if (isset($ut)) {
             $db = $location->db();
             $ut = $db->fromDateTime($ut);
             $ct = $db->getCurrentTimestamp();
             $cd = Q_Config::get('Places', 'cache', 'duration', 60 * 60 * 24 * 30);
             if ($ct - $ut < $cd) {
                 // there is a cached location stream that is still viable
                 return $location;
             }
         }
     }
     $key = Q_Config::expect('Places', 'google', 'keys', 'server');
     $query = http_build_query(array('key' => $key, 'placeid' => $placeId));
     $url = "https://maps.googleapis.com/maps/api/place/details/json?{$query}";
     $ch = curl_init();
     curl_setopt($ch, CURLOPT_URL, $url);
     curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
     $json = curl_exec($ch);
     curl_close($ch);
     $response = json_decode($json, true);
     if (empty($response['result'])) {
         throw new Q_Exception("Places_Location::stream: Couldn't obtain place information for {$placeId}");
     }
     if (!empty($response['error_message'])) {
         throw new Q_Exception("Places_Location::stream: " . $response['error_message']);
     }
     $result = $response['result'];
     $attributes = array('title' => $result['name'], 'latitude' => $result['geometry']['location']['lat'], 'longitude' => $result['geometry']['location']['lng'], 'viewport' => $result['geometry']['viewport'], 'phoneNumber' => Q::ifset($result, 'international_phone_number', null), 'phoneFormatted' => Q::ifset($result, 'formatted_phone_number', null), 'rating' => Q::ifset($result, 'rating', null), 'address' => Q::ifset($result, 'formatted_address', null));
     $location->title = $result['name'];
     $location->setAttribute($attributes);
     $location->type = 'Places/location';
     $location->save();
     return $location;
 }