Example #1
0
    function startup(&$controller)
    {
        $this->c =& $controller;
        if (!$this->runPlugin($controller)) {
            return false;
        }
        // Initialize vars
        $center = array();
        $address = '';
        $lat = 0;
        $lon = 0;
        if (!isset($controller->Config)) {
            $controller->Config = Configure::read('JreviewsSystem.Config');
        }
        if (!isset($controller->Access)) {
            $controller->Config = Configure::read('JreviewsSystem.Access');
        }
        $this->max_radius = Sanitize::getInt($controller->Config, 'geomaps.max_radius', $this->max_radius);
        $this->jr_lat = Sanitize::getString($controller->Config, 'geomaps.latitude');
        $this->jr_lon = Sanitize::getString($controller->Config, 'geomaps.longitude');
        if ($this->jr_lat == '' || $this->jr_lon == '') {
            return false;
        }
        // Setup vars used in startup and other plugin methods
        $this->google_url = Sanitize::getString($this->c->Config, 'geomaps.google_url', 'http://maps.google.com');
        $this->google_api_key = trim(Sanitize::getString($controller->Config, 'geomaps.google_key'));
        $this->google_api_url = $this->google_url . "/maps?file=api&v=2&async=2&key={$this->google_api_key}&sensor=false";
        $search_method = Sanitize::getString($controller->Config, 'geomaps.search_method', 'address');
        // address/disabled
        $search_address_field = Sanitize::getString($controller->Config, 'geomaps.advsearch_input');
        $default_radius = Sanitize::getString($controller->Config, 'geomaps.radius');
        $this->distance_metric = array('mi' => __t("Miles", true), 'km' => __t("Km", true));
        $this->distance_in = Sanitize::getString($controller->Config, 'geomaps.radius_metric', 'mi');
        $this->jr_address1 = Sanitize::getString($controller->Config, 'geomaps.address1');
        $this->jr_address2 = Sanitize::getString($controller->Config, 'geomaps.address2');
        $this->jr_city = Sanitize::getString($controller->Config, 'geomaps.city');
        $this->jr_state = Sanitize::getString($controller->Config, 'geomaps.state');
        $this->jr_postal_code = Sanitize::getString($controller->Config, 'geomaps.postal_code');
        $this->jr_country = Sanitize::getString($controller->Config, 'geomaps.country');
        $this->country_def = Sanitize::getString($controller->Config, 'geomaps.default_country');
        $this->gid = $controller->Access->gid;
        $this->address_fields = array_filter(array('address1' => $this->jr_address1, 'address2' => $this->jr_address2, 'city' => $this->jr_city, 'state' => $this->jr_state, 'postal_code' => $this->jr_postal_code, 'country' => $this->jr_country));
        $this->geo_fields = array('lat' => $this->jr_lat, 'lon' => $this->jr_lon);
        $this->c->set(array('address_fields' => $this->address_fields, 'geo_fields' => $this->geo_fields));
        /**
         * Address search checks
         */
        if (isset($controller->data['Field']['Listing'])) {
            $address = Sanitize::getString($controller->data['Field']['Listing'], $search_address_field);
        } else {
            $address = Sanitize::getString($controller->params, $search_address_field);
            $lat = Sanitize::getFloat($controller->params, $this->jr_lat);
            $lon = Sanitize::getFloat($controller->params, $this->jr_lon);
        }
        /**
         * Plugin does different things for different controller methods
         */
        switch ($controller->name) {
            case 'com_content':
                $this->published = true;
                $controller->Listing->cacheCallbacks[] = 'plgAfterAfterFind';
                $controller->Listing->fields[] = "`Field`.{$this->jr_lat} AS `Geomaps.lat`";
                $controller->Listing->fields[] = "`Field`.{$this->jr_lon} AS `Geomaps.lon`";
                $controller->Listing->fields[] = "JreviewsCategory.marker_icon AS `Geomaps.icon`";
                break;
            case 'listings':
                switch ($controller->action) {
                    // Load the geomaps js library
                    case 'create':
                        // Submit a new listing
                    // Submit a new listing
                    case 'edit':
                        // Edit a listing
                        $this->published = true;
                        $Html = new HtmlHelper();
                        $Html->app = 'jreviews';
                        $jsGlobals = 'var GeomapsGoogleApi = "' . $this->google_api_url . '";';
                        $jsGlobals .= 'var jr_lat = "' . $this->jr_lat . '";';
                        $jsGlobals .= 'var jr_lon = "' . $this->jr_lon . '";';
                        $jsGlobals .= 'var jr_country_def = "' . $this->country_def . '";';
                        $jsGlobals .= 'var geoAddressObj = {};';
                        foreach ($this->address_fields as $key => $field) {
                            $jsGlobals .= "geoAddressObj.{$key} = '{$field}';";
                        }
                        cmsFramework::addScript($controller->makeJS($jsGlobals), true);
                        $Html->js('geomaps', true);
                        if ($controller->action == 'edit') {
                            $mapit_field = Sanitize::getString($controller->Config, 'geomaps.mapit_field');
                            if ($mapit_field) {
                                $response = "jQuery(document).ready(function() { \r\n                                    jQuery('#{$mapit_field}','#jr_listingForm').after('<span id=\"gm_geocode\">\r\n                                        <input class=\"jrButton\" type=\"button\" onclick=\"geomaps.mapPopupSimple();\" value=\"" . __t("Map it", true) . "\" />&nbsp;\r\n                                        <input class=\"jrButton\" type=\"button\" onclick=\"geomaps.clearLatLng();\" value=\"" . __t("Clear LatLng", true) . "\" />\r\n                                    </span>');\r\n                                });";
                                cmsFramework::addScript($controller->makeJS($response), true);
                            }
                        }
                        break;
                        // Add geomaps buttons after form is loaded
                    // Add geomaps buttons after form is loaded
                    case '_loadForm':
                        // New listing - Loads submit listing form after category selection
                        $this->published = true;
                        $mapit_field = Sanitize::getString($controller->Config, 'geomaps.mapit_field');
                        if ($mapit_field) {
                            $response = array();
                            $response[] = "\r\n                                jQuery('#gm_geocode').remove();jQuery('#{$mapit_field}','#jr_listingForm').after('<span id=\"gm_geocode\"><input class=\"jrButton\" type=\"button\" onclick=\"geomaps.mapPopupSimple();\" value=\"" . __t("Map it", true) . "\" />&nbsp;<input class=\"jrButton\" type=\"button\" onclick=\"geomaps.clearLatLng();\" value=\"" . __t("Clear LatLng", true) . "\" /></span>');\r\n                                jQuery('#gm_geocode').find(':input').removeAttr('disabled');\r\n                            ";
                            $controller->afterAjaxResponse = $response;
                        }
                        break;
                    case '_save':
                        // Checks if
                        $isNew = Sanitize::getInt($controller->data['Listing'], 'id', 0) == 0 ? true : false;
                        if (Sanitize::getInt($controller->Config, 'geomaps.autogeocode_new') && $isNew && isset($controller->data['Field']) && (Sanitize::getFloat($controller->data['Field']['Listing'], $this->jr_lat, null) == null || Sanitize::getFloat($controller->data['Field']['Listing'], $this->jr_lon, null) == null)) {
                            // Build whole address from fields
                            $address = '';
                            foreach ($this->address_fields as $key => $field) {
                                ${$field} = Sanitize::getVar($controller->data['Field']['Listing'], $field, '');
                                if (${$field} != '') {
                                    $address .= ' ' . ${$field};
                                } elseif ($field == 'section') {
                                    $address .= " " . Sanitize::getString($controller->data, 'section');
                                } elseif ($field == 'parent_category') {
                                    $address .= " " . Sanitize::getString($controller->data, 'parent_category');
                                } elseif ($field == 'category') {
                                    $address .= " " . Sanitize::getString($controller->data, 'category');
                                }
                            }
                            if ($address != '' && !Sanitize::getVar($controller->data['Field']['Listing'], $this->jr_country, false) && $this->country_def != '') {
                                $address .= ' ' . $this->country_def;
                            }
                            if ($address != '') {
                                // Geocode address
                                App::import('Component', 'geocoding');
                                $Geocoding = ClassRegistry::getClass('GeocodingComponent');
                                $Geocoding->Config =& $controller->Config;
                                $response = $Geocoding->geocode($address);
                                if ($response['status'] == 200) {
                                    $controller->data['Field']['Listing'][$this->jr_lat] = $response['lat'];
                                    $controller->data['__raw']['Field']['Listing'][$this->jr_lat] = $response['lat'];
                                    $controller->data['Field']['Listing'][$this->jr_lon] = $response['lon'];
                                    $controller->data['__raw']['Field']['Listing'][$this->jr_lon] = $response['lon'];
                                }
                            }
                        }
                        break;
                }
                break;
            case 'admin_listings':
                switch ($controller->action) {
                    case 'index':
                    case 'browse':
                    case 'moderation':
                        App::import('Helper', 'html');
                        $Html = new HtmlHelper();
                        $Html->app = 'jreviews';
                        $jsGlobals = 'var GeomapsGoogleApi = "' . $this->google_api_url . '";';
                        $jsGlobals .= 'var jr_lat = "' . $this->jr_lat . '";';
                        $jsGlobals .= 'var jr_lon = "' . $this->jr_lon . '";';
                        $jsGlobals .= 'var jr_country_def = "' . $this->country_def . '";';
                        $jsGlobals .= 'var geoAddressObj = {};';
                        foreach ($this->address_fields as $key => $field) {
                            $jsGlobals .= "geoAddressObj.{$key} = '{$field}';";
                        }
                        if ($controller->action == 'moderation') {
                            ?>
                        <script type="text/javascript">
                        /* <![CDATA[ */
                        <?php 
                            echo $jsGlobals;
                            ?>
                        if(null==jQuery('body').data('geomaps')){
                            jQuery.getScript('<?php 
                            echo $this->locateScript('geomaps');
                            ?>
',function(){jQuery('body').data('geomaps',1)});
                        }                            
                        /* ]]> */
                        </script>
                        <?php 
                        } else {
                            cmsFramework::addScript($controller->makeJS($jsGlobals), true);
                            $Html->js('geomaps', true);
                        }
                        break;
                    case 'edit':
                        $mapit_field = Sanitize::getString($controller->Config, 'geomaps.mapit_field');
                        if ($mapit_field) {
                            $response = "jQuery('#{$mapit_field}').after('<span id=\"gm_geocode\"><input class=\"jrButton\" type=\"button\" onclick=\"geomaps.mapPopupSimple();\" value=\"" . __t("Map it", true) . "\" />&nbsp;<input class=\"jrButton\" type=\"button\" onclick=\"geomaps.clearLatLng();\" value=\"" . __t("Clear LatLng", true) . "\" /></span>');";
                            $controller->pluginResponse = $response;
                        }
                        break;
                }
                break;
                // A search was performed, make distance the default ordering and copy the entered address to the search address field
            // A search was performed, make distance the default ordering and copy the entered address to the search address field
            case 'search':
                if ($search_method == 'disabled' || $address == '') {
                    return;
                }
                if ($controller->action == '_process') {
                    $this->published = true;
                    // Enable the callbacks for this controller/method
                    // Make distance the default ordering
                    $controller->Config->list_order_default = 'distance';
                    if ($address != '' && in_array($search_method, array('address'))) {
                        $controller->data['Field']['Listing'][$search_address_field] = $address;
                        // Append default country
                        if ($this->country_def != '') {
                            $address .= ' ' . $this->country_def;
                        }
                        // Geocode address
                        App::import('Component', 'geocoding');
                        $Geocoding = ClassRegistry::getClass('GeocodingComponent');
                        $Geocoding->Config =& $controller->Config;
                        $response = $Geocoding->geocode($address);
                        if ($response['status'] == 200) {
                            $center = $response;
                        }
                        if ($center && !empty($center)) {
                            $controller->data['Field']['Listing'][$this->jr_lat] = $center['lat'];
                            $controller->data['Field']['Listing'][$this->jr_lon] = $center['lon'];
                            unset($controller->data['Field']['Listing'][$this->jr_lat . '_operator']);
                            unset($controller->data['Field']['Listing'][$this->jr_lon . '_operator']);
                        }
                    }
                }
                break;
                // Display search results
            // Display search results
            case 'categories':
                $controller->Listing->fields[] = "`Field`.{$this->jr_lat} AS `Geomaps.lat`";
                $controller->Listing->fields[] = "`Field`.{$this->jr_lon} AS `Geomaps.lon`";
                $controller->Listing->fields[] = "JreviewsCategory.marker_icon AS `Geomaps.icon`";
                $this->published = true;
                // Enable the callbacks for this controller/method
                if ($search_method == 'disabled' || $lat == 0 || $lon == 0) {
                    return;
                }
                if ($controller->action == 'search') {
                    $radius = min(Sanitize::getFloat($controller->params, $this->radius_field, $default_radius), $this->max_radius);
                    if ($search_method == 'disabled') {
                        $this->published = false;
                        return;
                    }
                    if ($lat != 0 && $lon != 0) {
                        Configure::write('geomaps.enabled', true);
                        // Used to show the Distance ordering in the jreviews.php helper in JReviews.
                        $center = array('lat' => $lat, 'lon' => $lon);
                        // Send center coordinates to theme
                        $controller->set('GeomapsCenter', $center);
                        $sort = $controller->params['order'] = Sanitize::getString($controller->params, 'order', 'distance');
                        // Clear address and coordinate field from parameters because it shouldn't be used on distance searches. Instead we use lat/lon via custom condition below
                        unset($controller->params[$search_address_field], $controller->params['url'][$search_address_field], $controller->params[$this->jr_lat], $controller->params['url'][$this->jr_lat], $controller->params[$this->jr_lon], $controller->params['url'][$this->jr_lon]);
                        $controller->passedArgs['url'] = preg_replace('/\\/' . $search_address_field . _PARAM_CHAR . '[\\p{L}-\\s0-9]+/i', '', $controller->passedArgs['url']);
                        $controller->passedArgs['url'] = preg_replace('/\\/' . $search_address_field . _PARAM_CHAR . '[a-z0-9-\\s]+/i', '', $controller->passedArgs['url']);
                        // One above doesn't work well in all cases, but required for non-latin characters in address
                        $controller->passedArgs['url'] = preg_replace('/\\/' . $this->jr_lat . _PARAM_CHAR . '[\\-a-z0-9\\.\\s]+/i', '', $controller->passedArgs['url']);
                        $controller->passedArgs['url'] = preg_replace('/\\/' . $this->jr_lon . _PARAM_CHAR . '[\\-a-z0-9\\.\\s]+/i', '', $controller->passedArgs['url']);
                        // Create a square around the center to limite the number of rows processed in the zip code table
                        // http://www.free-zipcodes.com/
                        // http://www.mysqlconf.com/mysql2008/public/schedule/detail/347
                        $degreeDistance = $this->distance_in == 'mi' ? 69.172 : 40076 / 360;
                        $lat_range = $radius / $degreeDistance;
                        $lon_range = $radius / abs(cos($center['lat'] * pi() / 180) * $degreeDistance);
                        $min_lat = $center['lat'] - $lat_range;
                        $max_lat = $center['lat'] + $lat_range;
                        $min_lon = $center['lon'] - $lon_range;
                        $max_lon = $center['lon'] + $lon_range;
                        $squareArea = "`Field`.{$this->jr_lat} BETWEEN {$min_lat} AND {$max_lat} AND `Field`.{$this->jr_lon} BETWEEN {$min_lon} AND {$max_lon}";
                        // calculate the distance between two sets of longitude/latitude coordinates
                        // From http://www.mysqlconf.com/mysql2008/public/schedule/detail/347
                        if ($this->distance_in == 'km') {
                            $controller->Listing->fields['distance'] = "6371 * 2 * ASIN(SQRT(  POWER(SIN(({$center['lat']} - {$this->jr_lat}) * pi()/180 / 2), 2) +  \r\n                                    COS({$center['lat']} * pi()/180) *  COS({$this->jr_lat} * pi()/180) *  POWER(SIN(({$center['lon']} -{$this->jr_lon}) * pi()/180 / 2), 2)  )) AS `Geomaps.distance`";
                        }
                        if ($this->distance_in == 'mi') {
                            $controller->Listing->fields['distance'] = "3956 * 2 * ASIN(SQRT(  POWER(SIN(({$center['lat']} - {$this->jr_lat}) * pi()/180 / 2), 2) +  \r\n                                    COS({$center['lat']} * pi()/180) *  COS({$this->jr_lat} * pi()/180) *  POWER(SIN(({$center['lon']} -{$this->jr_lon}) * pi()/180 / 2), 2)  )) AS `Geomaps.distance`";
                        }
                        $controller->Listing->conditions[] = $squareArea;
                        if ($sort == 'distance') {
                            $controller->Listing->order[] = '`Geomaps.distance` ASC';
                        }
                        // Makes sure that only listings within given radius are shown because square limit might include further points
                        //                        $controller->Listing->having[] = '`Geomaps.distance` <= ' . (int) $radius;
                        // Override search theme suffix
                        $theme_suffix = Sanitize::getString($controller->Config, 'geomaps.search_suffix');
                        if ($theme_suffix != '') {
                            $controller->viewSuffix = $theme_suffix;
                        }
                    }
                }
                break;
        }
    }