235 lines
7.6 KiB
PHP
Executable File
235 lines
7.6 KiB
PHP
Executable File
<?php
|
|
if ( !class_exists( 'SM_XML_Search' ) ){
|
|
class SM_XML_Search{
|
|
// Register hook to perform the search
|
|
function sm_xml_search() {
|
|
add_action( 'template_redirect', array( &$this, 'init_search' ) );
|
|
}
|
|
|
|
// Inits the search process. Collects default options, search options, and queries DB
|
|
function init_search() {
|
|
if ( isset( $_GET['sm-xml-search'] ) ) {
|
|
global $wpdb, $simple_map;
|
|
remove_filter( 'the_title', 'at_title_check' );
|
|
|
|
$defaults = array(
|
|
'lat' => false,
|
|
'lng' => false,
|
|
'radius' => false,
|
|
'namequery' => false,
|
|
'query_type' => 'distance',
|
|
'address' => false,
|
|
'city' => false,
|
|
'state' => false,
|
|
'zip' => false,
|
|
'onlyzip' => false,
|
|
'country' => false,
|
|
'limit' => false,
|
|
'page' => false,
|
|
'pid' => 0,
|
|
);
|
|
$input = array_filter( array_intersect_key( $_GET, $defaults ) ) + $defaults;
|
|
|
|
$smtaxes = array();
|
|
if ( $taxonomies = get_object_taxonomies( 'sm-location' ) ) {
|
|
foreach ( $taxonomies as $key => $tax ) {
|
|
$phpsafe = str_replace( '-', '_', $tax );
|
|
$_GET += array( $phpsafe => '' );
|
|
$smtaxes[$tax] = $_GET[$phpsafe];
|
|
}
|
|
}
|
|
|
|
// Define my empty strings
|
|
$distance_select = $distance_having = $distance_order = '';
|
|
|
|
// We're going to do a hard limit to 5000 for now.
|
|
if ( !$input['limit'] || $input['limit'] > 250 || $input['limit'] == 0 ) {
|
|
$limit_int = 250;
|
|
$limit = "LIMIT 250";
|
|
}
|
|
else {
|
|
$limit_int = absint( $input['limit'] );
|
|
$limit = 'LIMIT ' . $limit_int;
|
|
}
|
|
$limit = apply_filters( 'sm-xml-search-limit', $limit );
|
|
|
|
|
|
if ( $input['page'] && $input['page'] < 250 ) {
|
|
$offset = 'OFFSET ' . ( absint($input['page']) - 1) * absint( $input['limit'] );
|
|
}
|
|
else {
|
|
$offset = '';
|
|
}
|
|
|
|
// Locations within specific distance or just get them all?
|
|
$distance_select = $wpdb->prepare( "( 3959 * ACOS( COS( RADIANS(%s) ) * COS( RADIANS( lat_tbl.meta_value ) ) * COS( RADIANS( lng_tbl.meta_value ) - RADIANS(%s) ) + SIN( RADIANS(%s) ) * SIN( RADIANS( lat_tbl.meta_value ) ) ) ) AS distance", $input['lat'], $input['lng'], $input['lat'] ) . ', ';
|
|
$distance_order = 'distance, ';
|
|
|
|
if ( $input['radius'] ) {
|
|
$input['radius'] = ( $input['radius'] < 1 ) ? 1 : $input['radius'];
|
|
$distance_having = $wpdb->prepare( "HAVING distance < %d", $input['radius'] );
|
|
}
|
|
|
|
$i = 1;
|
|
$taxonomy_join = '';
|
|
foreach ( array_filter( $smtaxes ) as $taxonomy => $tax_value ) {
|
|
$term_ids = explode( ',', $tax_value );
|
|
if ( $term_ids[0] == 'OR' ) {
|
|
unset( $term_ids[0] );
|
|
if ( empty( $term_ids ) ) {
|
|
continue;
|
|
}
|
|
$search_values = array( "IN (" . vsprintf( '%d' . str_repeat( ',%d', count( $term_ids ) - 1 ), $term_ids ) . ")" );
|
|
} else {
|
|
$search_values = array();
|
|
foreach ( $term_ids as $term_id ) {
|
|
$search_values[] = sprintf( '= %d', $term_id );
|
|
}
|
|
}
|
|
foreach ( $search_values as $search_value ) {
|
|
$taxonomy_join .= "
|
|
INNER JOIN
|
|
$wpdb->term_relationships AS term_rel_$i ON posts.ID = term_rel_$i.object_id
|
|
INNER JOIN
|
|
$wpdb->term_taxonomy AS tax_$i ON
|
|
term_rel_$i.term_taxonomy_id = tax_$i.term_taxonomy_id
|
|
AND tax_$i.taxonomy = '$taxonomy'
|
|
AND tax_$i.term_id $search_value
|
|
";
|
|
$i++;
|
|
}
|
|
}
|
|
// Find out how many items are in the table
|
|
$total_locations_sql = $wpdb->get_var( "
|
|
SELECT
|
|
COUNT(*)
|
|
FROM
|
|
$wpdb->posts AS posts
|
|
INNER JOIN
|
|
$wpdb->postmeta lat_tbl ON lat_tbl.post_id = posts.ID AND lat_tbl.meta_key = 'location_lat'
|
|
INNER JOIN
|
|
$wpdb->postmeta lng_tbl ON lng_tbl.post_id = posts.ID AND lng_tbl.meta_key = 'location_lng'
|
|
$taxonomy_join
|
|
WHERE
|
|
posts.post_type = 'sm-location'
|
|
AND posts.post_status = 'publish'
|
|
" );
|
|
|
|
$total_locations = absint($total_locations_sql);
|
|
$total_pages = ceil($total_locations / $limit_int); // use ceiling to round up -- 0.01 is still "1 page"
|
|
$this_page_number = absint($input['page']);
|
|
if($this_page_number < 1) {
|
|
$this_page_number = 1;
|
|
}
|
|
|
|
|
|
$sql = "SELECT
|
|
lat_tbl.meta_value AS lat,
|
|
lng_tbl.meta_value AS lng,
|
|
$distance_select
|
|
posts.ID,
|
|
posts.post_content,
|
|
posts.post_title
|
|
FROM
|
|
$wpdb->posts AS posts
|
|
INNER JOIN
|
|
$wpdb->postmeta lat_tbl ON lat_tbl.post_id = posts.ID AND lat_tbl.meta_key = 'location_lat'
|
|
INNER JOIN
|
|
$wpdb->postmeta lng_tbl ON lng_tbl.post_id = posts.ID AND lng_tbl.meta_key = 'location_lng'
|
|
$taxonomy_join
|
|
WHERE
|
|
posts.post_type = 'sm-location'
|
|
AND posts.post_status = 'publish'
|
|
GROUP BY
|
|
posts.ID
|
|
$distance_having
|
|
ORDER BY " . apply_filters( 'sm-location-sort-order', $distance_order . ' posts.post_name ASC', $input ) . " " . $limit . " " . $offset;
|
|
|
|
$sql = apply_filters( 'sm-xml-search-locations-sql', $sql );
|
|
|
|
// TODO: Consider using this to generate the marker node attributes in print_xml().
|
|
$location_field_map = array(
|
|
'location_address' => 'address',
|
|
'location_address2' => 'address2',
|
|
'location_city' => 'city',
|
|
'location_state' => 'state',
|
|
'location_zip' => 'zip',
|
|
'location_country' => 'country',
|
|
'location_phone' => 'phone',
|
|
'location_fax' => 'fax',
|
|
'location_email' => 'email',
|
|
'location_url' => 'url',
|
|
'location_special' => 'special',
|
|
);
|
|
|
|
$options = $simple_map->get_options();
|
|
$show_permalink = !empty( $options['enable_permalinks'] );
|
|
|
|
if ( $locations = $wpdb->get_results( $sql ) ) {
|
|
// Start looping through all locations i found in the radius
|
|
foreach ( $locations as $key => $value ) {
|
|
// Add postmeta data to location
|
|
$custom_fields = get_post_custom( $value->ID );
|
|
foreach ( $location_field_map as $key => $field ) {
|
|
if ( isset( $custom_fields[$key][0] ) ) {
|
|
$value->$field = $custom_fields[$key][0];
|
|
}
|
|
else {
|
|
$value->$field = '';
|
|
}
|
|
}
|
|
|
|
$value->postid = $value->ID;
|
|
$value->name = apply_filters( 'the_title', $value->post_title );
|
|
|
|
$the_content = trim( $value->post_content );
|
|
if ( !empty( $the_content ) ) {
|
|
$the_content = apply_filters( 'the_content', $the_content );
|
|
}
|
|
$value->description = $the_content;
|
|
|
|
$value->permalink = '';
|
|
if ( $show_permalink ) {
|
|
$value->permalink = get_permalink( $value->ID );
|
|
$value->permalink = apply_filters( 'the_permalink', $value->permalink );
|
|
}
|
|
|
|
// List all terms for all taxonomies for this post
|
|
$value->taxes = array();
|
|
foreach ( $smtaxes as $taxonomy => $tax_value ) {
|
|
$phpsafe_tax = str_replace( '-', '_', $taxonomy );
|
|
$local_tax_names = '';
|
|
|
|
// Get all taxes for this post
|
|
if ( $local_taxes = wp_get_object_terms( $value->ID, $taxonomy, array( 'fields' => 'names' ) ) ) {
|
|
$local_tax_names = implode( ', ', $local_taxes );
|
|
}
|
|
|
|
$value->taxes[$phpsafe_tax] = $local_tax_names;
|
|
}
|
|
}
|
|
} else {
|
|
// Print empty XML
|
|
$locations = array();
|
|
}
|
|
|
|
$locations = apply_filters( 'sm-xml-search-locations', $locations );
|
|
$output = array('locations' => $locations, 'total_locations' => $total_locations, 'total_pages' => $total_pages, 'this_page' => $this_page_number);
|
|
$this->print_json( $output, $smtaxes );
|
|
}
|
|
}
|
|
|
|
// Prints the JSON output
|
|
function print_json( $dataset, $smtaxes ) {
|
|
header( 'Status: 200 OK', false, 200 );
|
|
header( 'Content-type: application/json' );
|
|
do_action( 'sm-xml-search-headers' );
|
|
|
|
do_action( 'sm-print-json', $dataset, $smtaxes );
|
|
|
|
echo json_encode( $dataset );
|
|
die();
|
|
}
|
|
}
|
|
}
|