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
}
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
}
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
}
Example #4
0
/**
 * Get a summary of streams related to the specified user's
 * "Streams/user/interests" stream
 *
 * @param {array} $_REQUEST 
 *   @param {string} [$_REQUEST.userId=loggedInUserId] userId
 * @return {void}
 */
function Streams_interest_response_interests()
{
    $user = Users::loggedInUser();
    $userId = Q::ifset($_REQUEST, 'userId', null);
    if ($user and $userId and $userId != $user->id and Q_Config::get('Streams', 'interests', 'allowClientQueries', false)) {
        throw new Q_Exception("Client queries are restricted, as per Streams/interests/allowClientQueries");
    }
    if ($userId) {
        $user = Users_User::fetch($userId);
    }
    if (!$user) {
        throw new Users_Exception_NotLoggedIn();
    }
    return Streams_Category::getRelatedTo($user->id, 'Streams/user/interests', 'Streams/interests');
}
Example #5
0
/**
 * Used to set the user's location from geolocation data.
 * @param $_REQUEST
 * @param [$_REQUEST.latitude] The new latitude. If set, must also specify longitude.
 * @param [$_REQUEST.longitude] The new longitude. If set, must also specify latitude.
 * @param [$_REQUEST.zipcode] The new zip code. Can be set instead of latitude, longitude.
 * @param [$_REQUEST.miles] The distance around their location around that the user is interested in
 * @param [$_REQUEST.subscribe] Whether to subscribe to all the local interests at the new location.
 * @param [$_REQUEST.unsubscribe] Whether to unsubscribe from all the local interests at the old location.
 * @param [$_REQUEST.accuracy]
 * @param [$_REQUEST.altitude]
 * @param [$_REQUEST.altitudeAccuracy]
 * @param [$_REQUEST.heading]
 * @param [$_REQUEST.speed]
 * @param [$_REQUEST.timezone]
 * @param [$_REQUEST.placeName] optional
 * @param [$_REQUEST.state] optional
 * @param [$_REQUEST.country] optional
 */
function Places_geolocation_post()
{
    $user = Users::loggedInUser(true);
    $stream = Places_Location::userStream();
    $oldLatitude = $stream->getAttribute('latitude');
    $oldLongitude = $stream->getAttribute('longitude');
    $oldMiles = $stream->getAttribute('miles');
    $fields = array('accuracy', 'altitude', 'altitudeAccuracy', 'heading', 'latitude', 'longitude', 'speed', 'miles', 'zipcode', 'timezone', 'placeName', 'state', 'country');
    $attributes = Q::take($_REQUEST, $fields);
    if (isset($attributes['latitude']) xor isset($attributes['longitude'])) {
        throw new Q_Exception("When specifying latitude,longitude you must specify both", array('latitude', 'longitude'));
    }
    if (!empty($attributes['zipcode']) and !isset($attributes['latitude'])) {
        $z = new Places_Zipcode();
        $z->countryCode = 'US';
        $z->zipcode = $attributes['zipcode'];
        if ($z->retrieve()) {
            $attributes['latitude'] = $z->latitude;
            $attributes['longitude'] = $z->longitude;
            $attributes['country'] = $z->countryCode;
        } else {
            throw new Q_Exception_MissingRow(array('table' => 'zipcode', 'criteria' => $attributes['zipcode']), 'zipcode');
        }
    }
    $attributes['miles'] = Q::ifset($attributes, 'miles', $stream->getAttribute('miles', Q_Config::expect('Places', 'nearby', 'defaultMiles')));
    if (empty($attributes['zipcode']) and isset($attributes['latitude'])) {
        $zipcodes = Places_Zipcode::nearby($attributes['latitude'], $attributes['longitude'], $attributes['miles'], 1);
        if ($zipcode = $zipcodes ? reset($zipcodes) : null) {
            $attributes['zipcode'] = $zipcode->zipcode;
            $attributes['placeName'] = $zipcode->placeName;
            $attributes['state'] = $zipcode->state;
            $attributes['country'] = $zipcode->countryCode;
        }
    }
    $stream->setAttribute($attributes);
    $stream->save();
    $stream->post($user->id, array('type' => 'Places/location/updated', 'content' => '', 'instructions' => $stream->getAllAttributes()), true);
    $shouldUnsubscribe = !empty($_REQUEST['unsubscribe']) && isset($oldMiles);
    $shouldSubscribe = !empty($_REQUEST['subscribe']);
    $noChange = false;
    $latitude = $stream->getAttribute('latitude');
    $longitude = $stream->getAttribute('longitude');
    $miles = $stream->getAttribute('miles');
    if ($shouldUnsubscribe and $shouldSubscribe and abs($latitude - $oldLatitude) < 0.0001 and abs($longitude - $oldLongitude) < 0.0001 and abs($miles - $oldMiles) < 0.001) {
        $noChange = true;
    }
    if (!$noChange) {
        if ($shouldUnsubscribe or $shouldSubscribe) {
            $myInterests = Streams_Category::getRelatedTo($user->id, 'Streams/user/interests', 'Streams/interest');
            if (!isset($myInterests)) {
                $myInterests = array();
            }
        }
        if ($shouldUnsubscribe) {
            // TODO: implement mass unsubscribe
            foreach ($myInterests as $weight => $info) {
                Places_Nearby::unsubscribe($oldLatitude, $oldLongitude, $oldMiles, $info[0], array('transform' => array('Places_Interest', '_transform'), 'title' => $info[2], 'skipAccess' => true));
            }
            $attributes['unsubscribed'] = Places_Nearby::unsubscribe($oldLatitude, $oldLongitude, $oldMiles);
        }
        if ($shouldSubscribe) {
            // TODO: implement mass subscribe
            foreach ($myInterests as $weight => $info) {
                Places_Nearby::subscribe($latitude, $longitude, $miles, $info[0], array('transform' => array('Places_Interest', '_transform'), 'create' => array('Places_Interest', '_create'), 'title' => $info[2], 'skipAccess' => true));
            }
            $attributes['subscribed'] = Places_Nearby::subscribe($latitude, $longitude, $miles);
        }
    }
    $attributes['stream'] = $stream;
    Q_Response::setSlot('attributes', $attributes);
    Q::event("Places/geolocation", $attributes, 'after');
}
Example #6
0
/**
 * Used to set the user's location from geolocation data.
 * @class HTTP Places geolocation
 * @method post
 * @param $_REQUEST
 * @param [$_REQUEST.latitude] The new latitude. If set, must also specify longitude.
 * @param [$_REQUEST.longitude] The new longitude. If set, must also specify latitude.
 * @param [$_REQUEST.zipcode] The new zip code. Can be set instead of latitude, longitude.
 * @param [$_REQUEST.miles] The distance around their location around that the user is interested in
 * @param [$_REQUEST.subscribe] Whether to subscribe to all the local interests at the new location.
 * @param [$_REQUEST.unsubscribe] Whether to unsubscribe from all the local interests at the old location.
 * @param [$_REQUEST.accuracy]
 * @param [$_REQUEST.altitude]
 * @param [$_REQUEST.altitudeAccuracy]
 * @param [$_REQUEST.heading]
 * @param [$_REQUEST.speed]
 * @param [$_REQUEST.timezone]
 * @param [$_REQUEST.placeName] optional
 * @param [$_REQUEST.state] optional
 * @param [$_REQUEST.country] optional
 */
function Places_geolocation_post()
{
    $user = Users::loggedInUser(true);
    $stream = Places_Location::userStream();
    $oldLatitude = $stream->getAttribute('latitude');
    $oldLongitude = $stream->getAttribute('longitude');
    $oldMiles = $stream->getAttribute('miles');
    $fields = array('accuracy', 'altitude', 'altitudeAccuracy', 'heading', 'latitude', 'longitude', 'speed', 'miles', 'zipcode', 'timezone', 'placeName', 'state', 'country');
    $attributes = Q::take($_REQUEST, $fields);
    if (isset($attributes['latitude']) xor isset($attributes['longitude'])) {
        throw new Q_Exception("When specifying latitude,longitude you must specify both", array('latitude', 'longitude'));
    }
    if (!empty($attributes['zipcode']) and !isset($attributes['latitude'])) {
        $z = new Places_Zipcode();
        $z->countryCode = 'US';
        $z->zipcode = $attributes['zipcode'];
        if ($z->retrieve()) {
            $attributes['latitude'] = $z->latitude;
            $attributes['longitude'] = $z->longitude;
            $attributes['country'] = $z->countryCode;
        } else {
            throw new Q_Exception_MissingRow(array('table' => 'zipcode', 'criteria' => $attributes['zipcode']), 'zipcode');
        }
    }
    $attributes['miles'] = Q::ifset($attributes, 'miles', $stream->getAttribute('miles', Q_Config::expect('Places', 'nearby', 'defaultMiles')));
    if (empty($attributes['zipcode']) and isset($attributes['latitude'])) {
        $zipcodes = Places_Zipcode::nearby($attributes['latitude'], $attributes['longitude'], $attributes['miles'], 1);
        if ($zipcode = $zipcodes ? reset($zipcodes) : null) {
            $attributes['zipcode'] = $zipcode->zipcode;
            $attributes['placeName'] = $zipcode->placeName;
            $attributes['state'] = $zipcode->state;
            $attributes['country'] = $zipcode->countryCode;
        }
    }
    $stream->setAttribute($attributes);
    $stream->save();
    $stream->post($user->id, array('type' => 'Places/location/updated', 'content' => '', 'instructions' => $stream->getAllAttributes()), true);
    $shouldUnsubscribe = !empty($_REQUEST['unsubscribe']) && isset($oldMiles);
    $shouldSubscribe = !empty($_REQUEST['subscribe']);
    $noChange = false;
    $latitude = $stream->getAttribute('latitude');
    $longitude = $stream->getAttribute('longitude');
    $miles = $stream->getAttribute('miles');
    if ($shouldUnsubscribe and $shouldSubscribe and abs($latitude - $oldLatitude) < 0.0001 and abs($longitude - $oldLongitude) < 0.0001 and abs($miles - $oldMiles) < 0.001) {
        $noChange = true;
    }
    $attributes['stream'] = $stream;
    Q_Response::setSlot('attributes', $attributes);
    if (!$noChange) {
        // Send the response and keep going.
        // WARN: this potentially ties up the PHP thread for a long time
        $timeLimit = Q_Config::get('Places', 'geolocation', 'timeLimit', 100000);
        ignore_user_abort(true);
        set_time_limit($timeLimit);
        Q_Dispatcher::response(true);
        session_write_close();
        if ($shouldUnsubscribe or $shouldSubscribe) {
            $myInterests = Streams_Category::getRelatedTo($user->id, 'Streams/user/interests', 'Streams/interests');
            if (!isset($myInterests)) {
                $myInterests = array();
            }
        }
        if ($shouldUnsubscribe and $oldLatitude and $oldLongitude and $oldMiles) {
            $results = array();
            foreach ($myInterests as $weight => $info) {
                $publisherId = $info[0];
                if (!isset($results[$publisherId])) {
                    $results[$publisherId] = array();
                }
                $results[$publisherId] = array_merge($results[$publisherId], Places_Interest::streams($publisherId, $oldLatitude, $oldLongitude, $info[2], array('miles' => $oldMiles, 'skipAccess' => true, 'forSubscribers' => true)));
            }
            foreach ($results as $publisherId => $streams) {
                Streams::unsubscribe($user->id, $publisherId, $streams, array('skipAccess' => true));
            }
            $attributes['unsubscribed'] = Places_Nearby::unsubscribe($oldLatitude, $oldLongitude, $oldMiles);
        }
        if ($shouldSubscribe) {
            $results = array();
            foreach ($myInterests as $weight => $info) {
                $publisherId = $info[0];
                if (!isset($results[$publisherId])) {
                    $results[$publisherId] = array();
                }
                $results[$publisherId] = array_merge($results[$publisherId], Places_Interest::streams($publisherId, $latitude, $longitude, $info[2], array('miles' => $miles, 'skipAccess' => true, 'forSubscribers' => true)));
            }
            foreach ($results as $publisherId => $streams) {
                Streams::subscribe($user->id, $publisherId, $streams, array('skipAccess' => true));
            }
            $attributes['subscribed'] = Places_Nearby::subscribe($latitude, $longitude, $miles);
        }
    }
    Q::event("Places/geolocation", $attributes, 'after');
}