public function get_results() { global $wpdb; $nr_results = !empty($this->options['sl_num_results']) ? $this->options['sl_num_results'] : 10; $metric = $this->options['unit_system'] == 'METRIC' ? 'km' : 'mi'; $radius = !empty($_REQUEST['wpseo-sl-radius']) ? $_REQUEST['wpseo-sl-radius'] : 99999; $sl_category_term = !empty($_REQUEST['wpseo-sl-category']) ? $_REQUEST['wpseo-sl-category'] : ''; $distances = array('in_radius' => 0, 'locations' => array()); $search_string = isset($_REQUEST['wpseo-sl-search']) ? esc_attr($_REQUEST['wpseo-sl-search']) : ''; if ($search_string == '') { return $distances; } // Add country name to search to improve search results $default_country = isset($this->options['default_country']) ? $this->options['default_country'] : ''; if ($default_country != '') { $search_string .= ' ' . WPSEO_Local_Frontend::get_country($default_country); } $response = wpseo_geocode_address($search_string); if (is_wp_error($response)) { return $response; } // Get lat/long if (empty($response->results[0])) { return new WP_Error('wpseo-get-results-error', __('No valid JSON response. We cannot complete the search.', 'yoast-local-seo')); } $result = $response->results[0]; $coordinates = !empty($result->geometry->location) ? $result->geometry->location : false; if (!$coordinates) { return new WP_Error('wpseo-get-results-error', __('No valid coordinates. We cannot complete the search.', 'yoast-local-seo')); } // Extend SQL with category filter $inner_join = ''; if ($sl_category_term != '') { $inner_join .= "\n\t\t\t\t\tINNER JOIN {$wpdb->term_relationships} AS term_rel ON p.ID = term_rel.object_id\n\t\t\t\t\tINNER JOIN {$wpdb->term_taxonomy} AS taxo ON term_rel.term_taxonomy_id = taxo.term_taxonomy_id \n\t\t\t\t\t\tAND taxo.taxonomy = 'wpseo_locations_category'\n\t\t\t\t\t\tAND taxo.term_id = {$sl_category_term}\n\t\t\t\t"; } // Get all coordinates from posts $sql = "SELECT p.ID, m1.meta_value as lat, m2.meta_value as lng \n\t\t\t\t\t\tFROM {$wpdb->posts} p \n\t\t\t\t\t\tINNER JOIN {$wpdb->postmeta} m1 ON p.ID = m1.post_id \n\t\t\t\t\t\tINNER JOIN {$wpdb->postmeta} m2 ON p.ID = m2.post_id\n\t\t\t\t\t\t{$inner_join}\n\t\t\t\t\t\tWHERE\n\t\t\t\t\t\t\tp.post_type = 'wpseo_locations' AND\n\t\t\t\t\t\t \tp.post_status = 'publish' AND\n\t\t\t\t\t\t\tm1.meta_key = '_wpseo_coordinates_lat' AND\n\t\t\t\t\t\t\tm2.meta_key = '_wpseo_coordinates_long'\n\t\t\t\t\t\tGROUP BY p.ID"; $locations = $wpdb->get_results($sql); // Calculate distance $in_radius = array(); $out_of_radius = array(); if (0 == $wpdb->num_rows) { return $distances; } foreach ($locations as $location) { // Skip locations with empty lat/long coordinates if (empty($location->lat) || empty($location->lng)) { continue; } $distance = $this->get_distance($coordinates->lat, $coordinates->lng, $location->lat, $location->lng); $distance_key = round($distance[$metric], 4) * 10000; // Filter on radius if ($distance[$metric] > $radius) { $out_of_radius[$distance[$metric]] = $location->ID; } else { $in_radius[(string) $distance_key] = $location->ID; } } if (0 == count($in_radius)) { // No results were found inside the given radius ksort($out_of_radius, SORT_NUMERIC); $distances['locations'] = array_slice($out_of_radius, 0, 1, true); return $distances; } ksort($in_radius, SORT_NUMERIC); $in_radius = array_slice($in_radius, 0, $nr_results, true); $distances['in_radius'] = count($in_radius); $distances['locations'] = $in_radius; return $distances; }
/** * Handles the CSV import and saves the locations */ public function handle_csv_import() { /** * Set the max execution time of this script to 3600 seconds (1 hour) * @TODO: Devide the upload in batches of 10 locations per batch. */ ini_set('max_execution_time', 3600); $upload_dir = wp_upload_dir(); $wpseo_upload_dir = $upload_dir["basedir"] . '/wpseo/import/'; $options = get_option($this->option_name); $count = 0; $last_imported = 0; if (isset($_POST['csv-import']) && check_admin_referer('wpseo_local_import_nonce', 'wpseo_local_import_nonce_field')) { $csv_path = $wpseo_upload_dir . basename($_FILES['wpseo']['name']['csvuploadlocations']); if (!empty($_FILES['wpseo']) && !move_uploaded_file($_FILES['wpseo']['tmp_name']['csvuploadlocations'], $csv_path)) { echo '<p class="error">' . __('Sorry, there was an error while uploading the CSV file.<br>Please make sure the ' . $wpseo_upload_dir . ' directory is writable (chmod 777).', 'yoast-local-seo') . '</p>'; } else { $is_simplemap_import = !empty($_POST['is-simplemap-import']) && $_POST['is-simplemap-import'] == '1'; $separator = ","; if (!empty($_POST['csv_separator']) && $_POST['csv_separator'] == "semicolon" && false == $is_simplemap_import) { $separator = ";"; } // Get location data from CSV $column_names = array("name", "address", "city", "zipcode", "state", "country", "phone", "phone2nd", "description", "image", "category", "url", "business_type", "opening_hours_monday_from", "opening_hours_monday_to", "opening_hours_monday_second_from", "opening_hours_monday_second_to", "opening_hours_tuesday_from", "opening_hours_tuesday_to", "opening_hours_tuesday_second_from", "opening_hours_tuesday_second_to", "opening_hours_wednesday_from", "opening_hours_wednesday_to", "opening_hours_wednesday_second_from", "opening_hours_wednesday_second_to", "opening_hours_thursday_from", "opening_hours_thursday_to", "opening_hours_thursday_second_from", "opening_hours_thursday_second_to", "opening_hours_friday_from", "opening_hours_friday_to", "opening_hours_friday_second_from", "opening_hours_friday_second_to", "opening_hours_saturday_from", "opening_hours_saturday_to", "opening_hours_saturday_second_from", "opening_hours_saturday_second_to", "opening_hours_sunday_from", "opening_hours_sunday_to", "opening_hours_sunday_second_from", "opening_hours_sunday_second_to", "notes_1", "notes_2", "notes_3"); if ($is_simplemap_import) { $column_names = array("name", "address", "address2", "city", "state", "zipcode", "country", "phone", "email", "fax", "url", "description", "special", "lat", "long", "pubdate", "category", "tag"); } $handle = fopen($csv_path, "r"); $locations = array(); $row = 0; while (($csvdata = fgetcsv($handle, 1000, $separator)) !== FALSE) { if ($row > 0) { $tmp_location = array(); for ($i = 0; $i < count($column_names); $i++) { // Skip columns for simplemap import if ($is_simplemap_import && in_array($column_names[$i], array('address2', 'email', 'url', 'special', 'pubdate', 'tag'))) { continue; } if (isset($csvdata[$i])) { $tmp_location[$column_names[$i]] = addslashes($csvdata[$i]); } } array_push($locations, $tmp_location); } $row++; } fclose($handle); $debug = false; global $wpseo_local_core; $business_types = $wpseo_local_core->get_local_business_types(); array_walk($business_types, 'wpseo_local_sanitize_business_types'); // Create WordPress posts in custom post type $errors = array(); foreach ($locations as $location) { // Create standard post data $current_post['ID'] = ''; $current_post['post_title'] = isset($location["name"]) ? $location["name"] : ''; $current_post['post_content'] = isset($location["description"]) ? $location["description"] : ''; $current_post['post_status'] = "publish"; $current_post['post_date'] = date("Y-m-d H:i:s", time()); $current_post['post_type'] = 'wpseo_locations'; $post_id = wp_insert_post($current_post); if (!$debug) { if (empty($location['lat']) && empty($location['long'])) { $full_address = wpseo_local_get_address_format($location['address'], true, $location['zipcode'], $location['city'], $location['state'], true, false, false); if (!empty($location['country'])) { $full_address .= ', ' . WPSEO_Local_Frontend::get_country($location['country']); } $geo_data = wpseo_geocode_address($full_address); if (!is_wp_error($geo_data) && !empty($geo_data->results[0])) { $location['lat'] = $geo_data->results[0]->geometry->location->lat; $location['long'] = $geo_data->results[0]->geometry->location->lng; } else { $location['lat'] = ''; $location['long'] = ''; if ($geo_data->get_error_code() == 'wpseo-query-limit') { $errors[] = sprintf(__('The usage of the Google Maps API has exceeds their limits. Please consider entering an API key in the %soptions%s', 'yoast-local-seo'), '<a href="' . admin_url('admin.php?page=wpseo_local') . '">', '</a>'); if (!empty($last_imported)) { $errors[] = sprintf(__('The last successfully imported location is <a href="%s" title="%s">%s</a>', 'yoast-local-seo'), get_edit_post_link($last_imported), get_the_title($last_imported), get_the_title($last_imported)); } break; } else { $errors[] = sprintf(__('Location <em>' . esc_attr($location["name"]) . '</em> could not be geo-coded. %sEdit this location%s.', 'yoast-local-seo'), '<a href="' . admin_url('post.php?post=' . esc_attr($post_id) . '&action=edit') . '">', '</a>'); } } } // Insert custom fields for location details if (!empty($post_id)) { add_post_meta($post_id, "_wpseo_business_name", isset($location["name"]) ? $location["name"] : '', true); add_post_meta($post_id, '_wpseo_business_address', isset($location["address"]) ? $location["address"] : '', true); add_post_meta($post_id, '_wpseo_business_city', isset($location["city"]) ? $location["city"] : '', true); add_post_meta($post_id, '_wpseo_business_state', isset($location["state"]) ? $location["state"] : '', true); add_post_meta($post_id, '_wpseo_business_zipcode', isset($location["zipcode"]) ? $location["zipcode"] : '', true); add_post_meta($post_id, '_wpseo_business_country', isset($location["country"]) ? $location["country"] : '', true); add_post_meta($post_id, '_wpseo_business_phone', isset($location["phone"]) ? $location["phone"] : '', true); add_post_meta($post_id, '_wpseo_business_fax', isset($location["fax"]) ? $location["fax"] : '', true); if (isset($location["phone_2nd"])) { add_post_meta($post_id, '_wpseo_business_phone_2nd', $location["phone_2nd"], true); } if (isset($location["email"])) { add_post_meta($post_id, '_wpseo_business_email', $location["email"], true); } if (isset($location['category'])) { wp_set_object_terms($post_id, $location['category'], 'wpseo_locations_category'); } if (isset($location['business_type'])) { $business_type = $location['business_type']; if (false == in_array($business_type, array_keys($business_types))) { $business_type = array_search($business_type, $business_types); } add_post_meta($post_id, '_wpseo_business_type', $business_type, true); } if (isset($location['url'])) { add_post_meta($post_id, '_wpseo_business_url', $location['url'], true); } // Add notes for ($i = 0; $i < 3; $i++) { $n = $i + 1; if (!empty($location['notes_' . $n])) { add_post_meta($post_id, '_wpseo_business_notes_' . $n, $location['notes_' . $n]); } } add_post_meta($post_id, '_wpseo_coordinates_lat', $location["lat"], true); add_post_meta($post_id, '_wpseo_coordinates_long', $location["long"], true); $count++; $last_imported = $post_id; } // Add image as post thumbnail if (!empty($location['image'])) { $wpseo_local_core->insert_attachment($post_id, $location['image'], true); } // Opening hours foreach ($wpseo_local_core->days as $key => $day) { if (isset($location['opening_hours_' . $key . '_from']) && !empty($location['opening_hours_' . $key . '_from']) && isset($location['opening_hours_' . $key . '_to']) && !empty($location['opening_hours_' . $key . '_to'])) { if ('closed' == strtolower($location['opening_hours_' . $key . '_from']) || 'closed' == strtolower($location['opening_hours_' . $key . '_to'])) { add_post_meta($post_id, '_wpseo_opening_hours_' . $key . '_from', 'closed', true); } else { $time_from = strtotime($location['opening_hours_' . $key . '_from']); $time_to = strtotime($location['opening_hours_' . $key . '_to']); if (false !== $time_from && false !== $time_to) { add_post_meta($post_id, '_wpseo_opening_hours_' . $key . '_from', date('H:i', $time_from), true); add_post_meta($post_id, '_wpseo_opening_hours_' . $key . '_to', date('H:i', $time_to), true); } else { add_post_meta($post_id, '_wpseo_opening_hours_' . $key . '_from', 'closed', true); if (false === $time_from) { $errors[] = sprintf(__('%s is not a valid time notation', 'yoast-local-seo'), $location['opening_hours_' . $key . '_from']); } else { if (false === $time_to) { $errors[] = sprintf(__('%s is not a valid time notation', 'yoast-local-seo'), $location['opening_hours_' . $key . '_to']); } } } if (isset($location['opening_hours_' . $key . '_second_from']) && !empty($location['opening_hours_' . $key . '_second_from']) && isset($location['opening_hours_' . $key . '_second_to']) && !empty($location['opening_hours_' . $key . '_second_to'])) { $time_second_from = strtotime($location['opening_hours_' . $key . '_second_from']); $time_second_to = strtotime($location['opening_hours_' . $key . '_second_to']); if (false !== $time_second_from && false !== $time_second_to) { add_post_meta($post_id, '_wpseo_opening_hours_' . $key . '_second_from', date('H:i', $time_second_from), true); add_post_meta($post_id, '_wpseo_opening_hours_' . $key . '_second_to', date('H:i', $time_second_to), true); // Multiple openingtimes are set. Enable them in the backend. update_post_meta($post_id, '_wpseo_multiple_opening_hours', 'on', true); } else { add_post_meta($post_id, '_wpseo_opening_hours_' . $key . '_second_from', 'closed', true); if (false === $time_second_from) { $errors[] = sprintf(__('%s is not a valid time notation', 'yoast-local-seo'), $location['opening_hours_' . $key . '_second_from']); } else { if (false === $time_second_to) { $errors[] = sprintf(__('%s is not a valid time notation', 'yoast-local-seo'), $location['opening_hours_' . $key . '_second_to']); } } } } else { add_post_meta($post_id, '_wpseo_opening_hours_' . $key . '_second_from', 'closed', true); } } } else { add_post_meta($post_id, '_wpseo_opening_hours_' . $key . '_from', 'closed', true); } } } } $msg = ''; if ($count > 0) { $msg .= $count . ' locations found and successfully imported.<br/>'; } if (!empty($errors)) { $msg .= '<p>'; $msg .= '<strong>' . __('Some errors has occured', 'yoast-local-seo') . '</strong><br>'; foreach ($errors as $error) { $msg .= $error . '<br>'; } $msg .= '</p>'; } if ($msg != '') { echo '<div id="message" class="message updated" style="width:94%;"><p>' . $msg . '</p></div>'; } } } }
/** * Retrieves the lat/long coordinates from the Google Maps API * * @param Array $location_info Array with location info. Array structure: array( _wpseo_business_address, _wpseo_business_city, _wpseo_business_state, _wpseo_business_zipcode, _wpseo_business_country ) * @param bool $force_update Whether to force the update or not * @param int $post_id * * @return bool|array Returns coordinates in array ( Format: array( 'lat', 'long' ) ). False when call the Maps API did not succeed */ public function get_geo_data($location_info, $force_update = false, $post_id = 0) { $full_address = wpseo_local_get_address_format($location_info['_wpseo_business_address'], false, $location_info['_wpseo_business_zipcode'], $location_info['_wpseo_business_city'], $location_info['_wpseo_business_state'], true, false, false) . ', ' . WPSEO_Local_Frontend::get_country($location_info['_wpseo_business_country']); $coordinates = array(); if (($post_id === 0 || empty($post_id)) && isset($location_info['_wpseo_post_id'])) { $post_id = $location_info['_wpseo_post_id']; } if ($force_update || empty($location_info['_wpseo_coords']['lat']) || empty($location_info['_wpseo_coords']['long'])) { $results = wpseo_geocode_address($full_address); if (is_wp_error($results)) { return false; } if (isset($results->results[0]) && !empty($results->results[0])) { $coordinates['lat'] = $results->results[0]->geometry->location->lat; $coordinates['long'] = $results->results[0]->geometry->location->lng; if (wpseo_has_multiple_locations() && $post_id !== 0) { update_post_meta($post_id, '_wpseo_coordinates_lat', $coordinates['lat']); update_post_meta($post_id, '_wpseo_coordinates_long', $coordinates['long']); } else { $options = get_option('wpseo_local'); $options['location_coords_lat'] = $coordinates['lat']; $options['location_coords_long'] = $coordinates['long']; update_option('wpseo_local', $options); } } } else { $coordinates['lat'] = $location_info['_wpseo_coords']['lat']; $coordinates['long'] = $location_info['_wpseo_coords']['long']; } $return_array['coords'] = $coordinates; $return_array["full_address"] = $full_address; return $return_array; }