/** * 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'); }
/** * Call this function to unsubscribe from streams you previously subscribed to * using Places_Nearby::subscribe. * @method unsubscribe * @static * @param {double} $latitude The latitude of the coordinates to subscribe around * @param {double} $longitude The longitude of the coordinates to subscribe 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 publishing these streams. * Defaults to the app name in Q/app config. * @param {array} $options The options to pass to the unsubscribe function * @return {Array} Returns an array of up to four arrays of ($publisherId, $streamName) * of streams that were subscribed to. */ static function unsubscribe($latitude, $longitude, $miles, $publisherId = null, $options = array()) { $user = Users::loggedInUser(true); if (!isset($publisherId)) { $publisherId = Users::communityId(); } $options['forSubscribers'] = true; $options['miles'] = $miles; $streams = Places_Nearby::streams($publisherId, $latitude, $longitude, $options); return Streams::unsubscribe($user->id, $publisherId, $streams, $options); }
/** * Unsubscribe from a stream, to stop receiving notifications. * Posts a "Streams/unsubscribe" message to the stream. * Also posts a "Streams/unsubscribed" message to user's "Streams/participating" stream. * Does not change the actual subscription, but only the participant row. * (When subscribing again, the existing subscription will be used.) * @method unsubscribe * @param $options=array() {array} * @param {boolean} [$options.leave] set to true to also leave the streams * @param {boolean} [$options.userId] the user who is unsubscribing from the stream. Defaults to the logged-in user. * @param {boolean} [$options.skipAccess] if true, skip access check for whether user can join and subscribe * @return {Streams_Participant|null} */ function unsubscribe($options = array()) { $userId = $this->_verifyUser($options); $participants = Streams::unsubscribe($userId, $this->publisherId, array($this->name), $options); return $participants ? reset($participants) : null; }