Esempio n. 1
0
function Places_after_Streams_interest_add($params)
{
    $location = Places_Location::userStream();
    if ($params['subscribe'] and $location and $location->getAttribute('latitude') and $location->getAttribute('longitude') and $location->getAttribute('miles')) {
        Places_Nearby::subscribe($location->getAttribute('latitude'), $location->getAttribute('longitude'), $location->getAttribute('miles'), $params['publisherId'], array('transform' => array('Places_Interest', '_transform'), 'create' => array('Places_Interest', '_create'), 'title' => $params['title'], 'skipAccess' => true));
    }
}
function Places_after_Streams_interest_remove($params)
{
    $location = Places_Location::userStream();
    if ($location) {
        $latitude = $location->getAttribute('latitude');
        $longitude = $location->getAttribute('longitude');
        $miles = $location->getAttribute('miles');
        if ($latitude and $longitude and $miles) {
            Places_Nearby::unsubscribe($latitude, $longitude, $miles, $params['publisherId'], array('transform' => array('Places_Interest', '_transform'), 'title' => $params['title'], 'skipAccess' => true));
        }
    }
}
Esempio n. 3
0
function Places_geolocation_response_data()
{
    $requireLogin = Q_Config::get('Places', 'geolocation', 'requireLogin', false);
    if (!$requireLogin and isset($_REQUEST['latitude']) and isset($_REQUEST['longitude'])) {
        if (!Q_Config::get('Places', 'geolocation', 'allowClientQueries', false)) {
            throw new Q_Exception("Client queries are restricted, as per Places/geolocation/allowClientQueries");
        }
        $latitude = $_REQUEST['latitude'];
        $longitude = $_REQUEST['longitude'];
    } else {
        $user = Users::loggedInUser(true);
        $stream = Places_Location::userStream();
        $latitude = $stream->getAttribute('latitude');
        $longitude = $stream->getAttribute('longitude');
        $miles = $stream->getAttribute('miles');
    }
    $miles = Q::ifset($_REQUEST, 'miles', Q_Config::expect('Places', 'nearby', 'defaultMiles'));
    $zipcodes = Places_Zipcode::nearby($latitude, $longitude, $miles, 1);
    $zipcode = $zipcodes ? reset($zipcodes) : null;
    $result = array('requested' => compact('latitude', 'longitude'), 'countryCode' => $zipcode->countryCode, 'zipcode' => $zipcode->zipcode, 'placeName' => $zipcode->placeName, 'stateName' => $zipcode->stateName, 'state' => $zipcode->state, 'regionName' => $zipcode->regionName, 'region' => $zipcode->region, 'latitude' => $zipcode->latitude, 'longitude' => $zipcode->longitude);
    return $result;
}
Esempio n. 4
0
 /**
  * Get autocomplete results
  * @method autocomplete
  * @static
  * @param {string} $input The text (typically typed by a user) to find completions for
  * @param {boolean} [$throwIfBadValue=false]
  *  Whether to throw Q_Exception if the result contains a bad value
  * @param {array} [$types=array("establishment")] Can include "establishment", "locality", "sublocality", "postal_code", "country", "administrative_area_level_1", "administrative_area_level_2". Set to true to include all types.
  * @param {double} [$latitude=userLocation] Override the latitude of the coordinates to search around
  * @param {double} [$longitude=userLocation] Override the longitude of the coordinates to search around
  * @param {double} [$miles=25] Override the radius, in miles, to search around
  * @return {Streams_Stream|null}
  * @throws {Q_Exception} if a bad value is encountered and $throwIfBadValue is true
  */
 static function autocomplete($input, $throwIfBadValue = false, $types = null, $latitude = null, $longitude = null, $miles = 25)
 {
     $supportedTypes = array("establishment", "locality", "sublocality", "postal_code", "country", "administrative_area_level_1", "administrative_area_level_2");
     $input = strtolower($input);
     if (is_string($types)) {
         $types = explode(',', $types);
     } else {
         if ($types === true) {
             $types = null;
         }
     }
     if ($types) {
         foreach ($types as $type) {
             if (!in_array($type, $supportedTypes)) {
                 throw new Q_Exception_BadValue(array('internal' => '$types', 'problem' => "{$type} is not supported"));
             }
         }
     }
     if (empty($input)) {
         if ($throwIfBadValue) {
             throw new Q_Exception_RequiredField(array('field' => 'input'));
         }
         return null;
     }
     if (!isset($latitude) or !isset($longitude)) {
         if ($uls = Places_Location::userStream()) {
             $latitude = $uls->getAttribute('latitude', null);
             $longitude = $uls->getAttribute('longitude', null);
             if (!isset($miles)) {
                 $miles = $uls->getAttribute('miles', 25);
             }
         } else {
             // put some defaults
             $latitude = 40.5806032;
             $longitude = -73.9755244;
             $miles = 25;
         }
     }
     $pa = null;
     if (Q_Config::get('Places', 'cache', 'autocomplete', true)) {
         $pa = new Places_Autocomplete();
         $pa->query = $input;
         $pa->types = $types ? implode(',', $types) : '';
         $pa->latitude = $latitude;
         $pa->longitude = $longitude;
         $pa->miles = $miles;
         if ($pa->retrieve()) {
             $ut = $pa->updatedTime;
             if (isset($ut)) {
                 $db = $pa->db();
                 $ut = $db->fromDateTime($ut);
                 $ct = $db->getCurrentTimestamp();
                 $cd = Q_Config::get('Places', 'cache', 'duration', 60 * 60 * 24 * 30);
                 if ($ct - $ut < $cd) {
                     // there are cached autocomplete results that are still viable
                     return Q::json_decode($pa->results, true);
                 }
             }
         }
     }
     $key = Q_Config::expect('Places', 'google', 'keys', 'server');
     $location = "{$latitude},{$longitude}";
     $radius = ceil(1609.34 * $miles);
     if ($types === null) {
         unset($types);
     }
     $query = http_build_query(compact('key', 'input', 'types', 'location', 'radius'));
     $url = "https://maps.googleapis.com/maps/api/place/autocomplete/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['predictions'])) {
         throw new Q_Exception("Places::autocomplete: Couldn't obtain predictions for {$input}");
     }
     if (!empty($response['error_message'])) {
         throw new Q_Exception("Places::autocomplete: " . $response['error_message']);
     }
     $results = $response['predictions'];
     if ($pa) {
         $pa->results = json_encode($results);
         $pa->save();
     }
     return $results;
 }
Esempio n. 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');
}
Esempio n. 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');
}