| Server IP : 146.59.209.152 / Your IP : 216.73.216.46 Web Server : Apache System : Linux webm005.cluster131.gra.hosting.ovh.net 5.15.167-ovh-vps-grsec-zfs-classid #1 SMP Tue Sep 17 08:14:20 UTC 2024 x86_64 User : infrafs ( 43850) PHP Version : 8.2.29 Disable Function : _dyuweyrj4,_dyuweyrj4r,dl MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : OFF | Pkexec : OFF Directory : /home/i/n/f/infrafs/INFRABIKEIT/wp-content/plugins/ |
Upload File : |
inc/wpsl-functions.php 0000644 00000050341 15132722064 0011026 0 ustar 00 <?php
/**
* Collect all the parameters ( language, key, region )
* we need before making a request to the Google Maps API.
*
* @since 1.0.0
* @param string $api_key_type The type of API key we need to include ( server_key or browser_key ).
* @param boolean $geocode_params
* @return string $api_params The API parameters.
*/
function wpsl_get_gmap_api_params( $api_key_type, $geocode_params = false ) {
global $wpsl, $wpsl_settings;
$api_params = '';
$param_keys = array( 'language', 'region', 'key' );
/*
* The geocode params are included after the address so we need to
* use a '&' as the first char, but when the maps script is included on
* the front-end it does need to start with a '?'.
*/
$first_sep = ( $geocode_params ) ? '&' : '?';
foreach ( $param_keys as $param_key ) {
$option_key = ( $param_key == 'key' ) ? $api_key_type : $param_key;
/*
* Get the current language code if WPML or qTranslate-X is active.
* Otherwise get the param value from the settings var.
*/
if ( $option_key == 'language' && ( $wpsl->i18n->wpml_exists() || $wpsl->i18n->qtrans_exists() ) ) {
$param_val = $wpsl->i18n->check_multilingual_code();
} else {
$param_val = $wpsl_settings['api_' . $option_key];
}
if ( !empty( $param_val ) ) {
$api_params .= $param_key . '=' . $param_val . '&';
}
}
if ( $api_params ) {
$api_params = $first_sep . rtrim( $api_params, '&' );
}
// Do we need to include the autocomplete library?
if ( ( $wpsl_settings['autocomplete'] && $api_key_type == 'browser_key' ) || is_admin() ) {
$api_params .= '&libraries=places';
}
if ( $api_key_type == 'browser_key' ) {
$api_version = apply_filters( 'wpsl_gmap_api_version', 'quarterly' );
$api_params .= '&v=' . $api_version;
}
return apply_filters( 'wpsl_gmap_api_params', $api_params );
}
/**
* Get the default plugin settings.
*
* @since 1.0.0
* @return array $default_settings The default settings
*/
function wpsl_get_default_settings() {
$default_settings = array(
'api_browser_key' => '',
'api_server_key' => '',
'api_language' => 'en',
'api_region' => '',
'api_geocode_component' => 0,
'distance_unit' => 'km',
'max_results' => '[25],50,75,100',
'search_radius' => '10,25,[50],100,200,500',
'force_postalcode' => 0,
'marker_effect' => 'bounce',
'address_format' => 'city_state_zip',
'hide_distance' => 0,
'hide_country' => 0,
'show_contact_details' => 0,
'clickable_contact_details' => 0,
'auto_locate' => 1,
'autocomplete' => 0,
'autoload' => 1,
'autoload_limit' => 50,
'run_fitbounds' => 1,
'zoom_level' => 3,
'auto_zoom_level' => 15,
'start_name' => '',
'start_latlng' => '',
'height' => 350,
'map_type' => 'roadmap',
'map_style' => '',
'type_control' => 0,
'streetview' => 0,
'results_dropdown' => 1,
'radius_dropdown' => 1,
'category_filter' => 0,
'category_filter_type' => 'dropdown',
'infowindow_width' => 225,
'search_width' => 179,
'label_width' => 95,
'control_position' => 'left',
'scrollwheel' => 1,
'marker_clusters' => 0,
'cluster_zoom' => 0,
'cluster_size' => 0,
'new_window' => 0,
'reset_map' => 0,
'template_id' => 'default',
'listing_below_no_scroll' => 0,
'direction_redirect' => 0,
'more_info' => 0,
'store_url' => 0,
'phone_url' => 0,
'marker_streetview' => 0,
'marker_zoom_to' => 0,
'more_info_location' => 'info window',
'mouse_focus' => 0,
'start_marker' => 'red.png',
'store_marker' => 'blue.png',
'editor_country' => '',
'editor_hours' => wpsl_default_opening_hours(),
'editor_hour_input' => 'dropdown',
'editor_hour_format' => 12,
'editor_map_type' => 'roadmap',
'hide_hours' => 0,
'permalinks' => 0,
'permalink_remove_front' => 0,
'permalink_slug' => __( 'stores', 'wpsl' ),
'category_slug' => __( 'store-category', 'wpsl' ),
'infowindow_style' => 'default',
'show_credits' => 0,
'debug' => 0,
'deregister_gmaps' => 0,
'delay_loading' => 0,
'start_label' => __( 'Start location', 'wpsl' ),
'search_label' => __( 'Your location', 'wpsl' ),
'search_btn_label' => __( 'Search', 'wpsl' ),
'preloader_label' => __( 'Searching...', 'wpsl' ),
'radius_label' => __( 'Search radius', 'wpsl' ),
'no_results_label' => __( 'No results found', 'wpsl' ),
'results_label' => __( 'Results', 'wpsl' ),
'more_label' => __( 'More info', 'wpsl' ),
'directions_label' => __( 'Directions', 'wpsl' ),
'no_directions_label' => __( 'No route could be found between the origin and destination', 'wpsl' ),
'back_label' => __( 'Back', 'wpsl' ),
'street_view_label' => __( 'Street view', 'wpsl' ),
'zoom_here_label' => __( 'Zoom here', 'wpsl' ),
'error_label' => __( 'Something went wrong, please try again!', 'wpsl' ),
'limit_label' => __( 'API usage limit reached', 'wpsl' ),
'phone_label' => __( 'Phone', 'wpsl' ),
'fax_label' => __( 'Fax', 'wpsl' ),
'email_label' => __( 'Email', 'wpsl' ),
'url_label' => __( 'Url', 'wpsl' ),
'hours_label' => __( 'Hours', 'wpsl' ),
'category_label' => __( 'Category filter', 'wpsl' ),
'category_default_label' => __( 'Any', 'wpsl' )
);
return $default_settings;
}
/**
* Get the current plugin settings.
*
* @since 1.0.0
* @return array $setting The current plugin settings
*/
function wpsl_get_settings() {
$settings = get_option( 'wpsl_settings' );
if ( !$settings ) {
update_option( 'wpsl_settings', wpsl_get_default_settings() );
$settings = wpsl_get_default_settings();
}
return $settings;
}
/**
* Get a single value from the default settings.
*
* @since 1.0.0
* @param string $setting The value that should be restored
* @return string $wpsl_default_settings The default setting value
*/
function wpsl_get_default_setting( $setting ) {
global $wpsl_default_settings;
return $wpsl_default_settings[$setting];
}
/**
* Set the default plugin settings.
*
* @since 1.0.0
* @return void
*/
function wpsl_set_default_settings() {
$settings = get_option( 'wpsl_settings' );
if ( !$settings ) {
update_option( 'wpsl_settings', wpsl_get_default_settings() );
}
}
/**
* Return a list of the store templates.
*
* @since 1.2.20
* @return array $templates The list of default store templates
*/
function wpsl_get_templates() {
$templates = array(
array(
'id' => 'default',
'name' => __( 'Default', 'wpsl' ),
'path' => WPSL_PLUGIN_DIR . 'frontend/templates/default.php'
),
array(
'id' => 'below_map',
'name' => __( 'Show the store list below the map', 'wpsl' ),
'path' => WPSL_PLUGIN_DIR . 'frontend/templates/store-listings-below.php'
)
);
return apply_filters( 'wpsl_templates', $templates );
}
/**
* Return the days of the week.
*
* @since 2.0.0
* @return array $weekdays The days of the week
*/
function wpsl_get_weekdays() {
$weekdays = array(
'monday' => __( 'Monday', 'wpsl' ),
'tuesday' => __( 'Tuesday', 'wpsl' ),
'wednesday' => __( 'Wednesday', 'wpsl' ),
'thursday' => __( 'Thursday', 'wpsl' ),
'friday' => __( 'Friday', 'wpsl' ),
'saturday' => __( 'Saturday', 'wpsl' ),
'sunday' => __( 'Sunday' , 'wpsl' )
);
return $weekdays;
}
/**
* Get the default opening hours.
*
* @since 2.0.0
* @return array $opening_hours The default opening hours
*/
function wpsl_default_opening_hours() {
$current_version = get_option( 'wpsl_version' );
$opening_hours = array(
'dropdown' => array(
'monday' => array( '9:00 AM,5:00 PM' ),
'tuesday' => array( '9:00 AM,5:00 PM' ),
'wednesday' => array( '9:00 AM,5:00 PM' ),
'thursday' => array( '9:00 AM,5:00 PM' ),
'friday' => array( '9:00 AM,5:00 PM' ),
'saturday' => '',
'sunday' => ''
)
);
/* Only add the textarea defaults for users that upgraded from 1.x */
if ( version_compare( $current_version, '2.0', '<' ) ) {
$opening_hours['textarea'] = sprintf( __( 'Mon %sTue %sWed %sThu %sFri %sSat Closed %sSun Closed', 'wpsl' ), '9:00 AM - 5:00 PM' . "\n", '9:00 AM - 5:00 PM' . "\n", '9:00 AM - 5:00 PM' . "\n", '9:00 AM - 5:00 PM' . "\n", '9:00 AM - 5:00 PM' . "\n", "\n" ); //cleaner way without repeating it 5 times??
}
return $opening_hours;
}
/**
* Get the available map types.
*
* @since 2.0.0
* @return array $map_types The available map types
*/
function wpsl_get_map_types() {
$map_types = array(
'roadmap' => __( 'Roadmap', 'wpsl' ),
'satellite' => __( 'Satellite', 'wpsl' ),
'hybrid' => __( 'Hybrid', 'wpsl' ),
'terrain' => __( 'Terrain', 'wpsl' )
);
return $map_types;
}
/**
* Get the address formats.
*
* @since 2.0.0
* @return array $address_formats The address formats
*/
function wpsl_get_address_formats() {
$address_formats = array(
'city_state_zip' => __( '(city) (state) (zip code)', 'wpsl' ),
'city_comma_state_zip' => __( '(city), (state) (zip code)', 'wpsl' ),
'city_zip' => __( '(city) (zip code)', 'wpsl' ),
'city_comma_zip' => __( '(city), (zip code)', 'wpsl' ),
'zip_city_state' => __( '(zip code) (city) (state)', 'wpsl' ),
'zip_city' => __( '(zip code) (city)', 'wpsl' )
);
return apply_filters( 'wpsl_address_formats', $address_formats );
}
/**
* Make sure the provided map type is valid.
*
* If the map type is invalid the default is used ( roadmap ).
*
* @since 2.0.0
* @param string $map_type The provided map type
* @return string $map_type A valid map type
*/
function wpsl_valid_map_type( $map_type ) {
$allowed_map_types = wpsl_get_map_types();
if ( !array_key_exists( $map_type, $allowed_map_types ) ) {
$map_type = wpsl_get_default_setting( 'map_type' );
}
return $map_type;
}
/**
* Make sure the provided zoom level is valid.
*
* If the zoom level is invalid the default is used ( 3 ).
*
* @since 2.0.0
* @param string $zoom_level The provided zoom level
* @return string $zoom_level A valid zoom level
*/
function wpsl_valid_zoom_level( $zoom_level ) {
$zoom_level = absint( $zoom_level );
if ( ( $zoom_level < 1 ) || ( $zoom_level > 21 ) ) {
$zoom_level = wpsl_get_default_setting( 'zoom_level' );
}
return $zoom_level;
}
/**
* Get the max auto zoom levels for the map.
*
* @since 2.0.0
* @return array $max_zoom_levels The array holding the min - max zoom levels
*/
function wpsl_get_max_zoom_levels() {
$max_zoom_levels = array();
$zoom_level = array(
'min' => 10,
'max' => 21
);
$i = $zoom_level['min'];
while ( $i <= $zoom_level['max'] ) {
$max_zoom_levels[$i] = $i;
$i++;
}
return $max_zoom_levels;
}
/**
* The labels and the values that can be set through the settings page.
*
* @since 2.0.0
* @return array $labels The label names from the settings page.
*/
function wpsl_labels() {
$labels = array(
'search',
'search_btn',
'preloader',
'radius',
'no_results',
'results',
'more',
'directions',
'no_directions',
'back',
'street_view',
'zoom_here',
'error',
'phone',
'fax',
'email',
'url',
'hours',
'start',
'limit',
'category',
'category_default'
);
return $labels;
}
/**
* Callback for array_walk_recursive, sanitize items in a multidimensional array.
*
* @since 2.0.0
* @param string $item The value
* @param integer $key The key
*/
function wpsl_sanitize_multi_array( &$item, $key ) {
$item = sanitize_text_field( $item );
}
/**
* Check whether the array is multidimensional.
*
* @since 2.0.0
* @param array $array The array to check
* @return boolean
*/
function wpsl_is_multi_array( $array ) {
foreach ( $array as $value ) {
if ( is_array( $value ) ) return true;
}
return false;
}
/**
* @since 2.1.1
* @param string $address The address to geocode.
* @return array $response Either a WP_Error or the response from the Geocode API.
*/
function wpsl_call_geocode_api( $address ) {
$url = 'https://maps.googleapis.com/maps/api/geocode/json?address=' . urlencode( $address ) . wpsl_get_gmap_api_params( 'server_key', true );
$response = wp_remote_get( $url );
return $response;
}
/**
* Get the latlng for the provided address.
*
* This is used to geocode the address set as the start point on
* the settings page in case the autocomplete fails
* ( only happens when there is a JS error on the page ),
* or to get the latlng when the 'start_location' attr is set
* on the wpsl shortcode.
*
* @since 2.2
* @param string $address The address to geocode.
* @return array|void $latlng The returned latlng or nothing if there was an error.
*/
function wpsl_get_address_latlng( $address ) {
$latlng = '';
$response = wpsl_call_geocode_api( $address );
if ( !is_wp_error( $response ) ) {
$response = json_decode( $response['body'], true );
if ( $response['status'] == 'OK' ) {
$latlng = $response['results'][0]['geometry']['location']['lat'] . ',' . $response['results'][0]['geometry']['location']['lng'];
}
}
return $latlng;
}
/**
* Check if there's a transient that holds
* the coordinates for the passed address.
*
* If not, then we geocode the address and
* set the returned value in the transient.
*
* @since 2.2.11
* @param string $address The location to geocode
* @return string $latlng The coordinates of the geocoded location
*/
function wpsl_check_latlng_transient( $address ) {
$name_section = explode( ',', $address );
$transient_name = 'wpsl_' . trim( strtolower( $name_section[0] ) ) . '_latlng';
if ( false === ( $latlng = get_transient( $transient_name ) ) ) {
$latlng = wpsl_get_address_latlng( $address );
if ( $latlng ) {
set_transient( $transient_name, $latlng, 0 );
}
}
return $latlng;
}
/**
* Make sure the shortcode attributes are booleans
* when they are expected to be.
*
* @since 2.0.4
* @param array $atts Shortcode attributes
* @return array $atts Shortcode attributes
*/
function wpsl_bool_check( $atts ) {
foreach ( $atts as $key => $val ) {
if ( in_array( $val, array( 'true', '1', 'yes', 'on' ) ) ) {
$atts[$key] = true;
} else if ( in_array( $val, array( 'false', '0', 'no', 'off' ) ) ) {
$atts[$key] = false;
}
}
return $atts;
}
/**
* Create a string with random characters.
*
* @since 2.2.4
* @param int $length Used length
* @return string $random_chars Random characters
*/
function wpsl_random_chars( $length = 5 ) {
$random_chars = substr( str_shuffle( "abcdefghijklmnopqrstuvwxyz" ), 0, $length );
return $random_chars;
}
/**
* Deregister other Google Maps scripts.
*
* If plugins / themes also include the Google Maps library, then it can cause
* problems with the autocomplete function on the settings page and break
* the store locator on the front-end.
*
* @since 2.2.4
* @return void
*/
function wpsl_deregister_other_gmaps() {
global $wp_scripts;
foreach ( $wp_scripts->registered as $index => $script ) {
if ( ( strpos( $script->src, 'maps.google.com' ) !== false ) || ( strpos( $script->src, 'maps.googleapis.com' ) !== false ) && ( $script->handle !== 'wpsl-gmap' ) ) {
wp_deregister_script( $script->handle );
}
}
}
/**
* Return the used distance unit.
*
* @since 2.2.8
* @return string Either km or mi
*/
function wpsl_get_distance_unit() {
global $wpsl_settings;
return apply_filters( 'wpsl_distance_unit', $wpsl_settings['distance_unit'] );
}
/**
* Find the term ids for the provided term slugs.
*
* @since 2.2.10
* @param array $cat_list List of term slugs
* @return array $term_ids The term ids
*/
function wpsl_get_term_ids( $cat_list ) {
$term_ids = array();
$cats = explode( ',', $cat_list );
foreach ( $cats as $key => $term_slug ) {
$term_data = get_term_by( 'slug', $term_slug, 'wpsl_store_category' );
if ( isset( $term_data->term_id ) && $term_data->term_id ) {
$term_ids[] = $term_data->term_id;
}
}
return $term_ids;
}
/**
* Get the url to the admin-ajax.php
*
* @since 2.2.3
* @return string $ajax_url URL to the admin-ajax.php possibly with the WPML lang param included.
*/
function wpsl_get_ajax_url() {
$i18n = new WPSL_i18n();
$param = '';
if ( $i18n->wpml_exists() && defined( 'ICL_LANGUAGE_CODE' ) ) {
$param = '?lang=' . ICL_LANGUAGE_CODE;
}
$ajax_url = admin_url( 'admin-ajax.php' . $param );
return $ajax_url;
}
/**
* Get a list of the used meta fields.
*
* Used by add-ons and the REST-API.
*
* @since 2.2.14
* @param array $args Argument to grab the locations field. See the $defaults structure.
* @return array $fields
*/
function wpsl_get_location_fields( $args = array() ) {
// Required to make sure it works with API calls.
if ( !class_exists( 'WPSL_Metaboxes' ) ) {
require_once( WPSL_PLUGIN_DIR . 'admin/class-metaboxes.php' );
}
$metaboxes = new WPSL_Metaboxes();
$meta_fields = $metaboxes->meta_box_fields();
$fields = array();
$defaults = array(
'exclude' => array( 'country_iso' ),
'prefix' => '',
'set_values' => true
);
/**
* Parse incoming $args into an array and merge it with $defaults
*/
$args = wp_parse_args( $args, $defaults );
foreach ( $meta_fields as $k => $field_section ) {
foreach ( $field_section as $field_name => $field_value ) {
if ( in_array( $field_name, $args['exclude'] ) ) {
continue;
}
$fields[$args['prefix'] . $field_name] = ( $args['set_values'] ) ? $field_name : '';
}
}
return $fields;
} inc/class-borlabs-cookie.php 0000644 00000014733 15132722064 0012036 0 ustar 00 <?php
/**
* WPSL / Borlabs Cookie class
*
* @author Tijmen Smit
* @since 2.2.22
*/
if ( !defined( 'ABSPATH' ) ) exit;
if ( !class_exists( 'WPSL_Borlabs_Cookie' ) ) {
class WPSL_Borlabs_Cookie {
/**
* Class constructor
*/
public function __construct() {
if ( !is_admin() ) {
if (defined('BORLABS_COOKIE_VERSION') && version_compare(BORLABS_COOKIE_VERSION, '2.0', '>=')) {
add_filter( 'borlabsCookie/contentBlocker/modify/content/wpstorelocator', array( $this, 'update_content_blocker' ), 10, 2 );
} else {
add_filter( 'borlabsCookie/bct/modify_content/wpstorelocator', array( $this, 'update_content_blocker_backwards_compatibility' ), 10, 2 );
}
}
}
/**
* Check if the 'wpstorelocator' blocked content type exists.
* If this is not the case, then we create it.
*
* @since 2.2.22
* @return void
*/
public function maybe_enable_bct() {
$wpsl_bct_data = BorlabsCookieHelper()->getBlockedContentTypeDataByTypeId( 'wpstorelocator' );
if ( !$wpsl_bct_data ) {
$this->enable();
}
}
/**
* Add support for the delayed loading of the
* Google Maps library in the Borlabs Cookies plugin
* by adding a 'wpstorelocator' blocked content type.
*
* @since 2.2.22
* @return void
*/
public function enable() {
/**
* First, we delete old Blocked Content Types with the id wpstorelocator.
* If the id doesn't exist, nothing happens.
*
* Doing so ensures that both plugins work as intended.
*/
BorlabsCookieHelper()->deleteBlockedContentType( 'wpstorelocator' );
// Add new Blocked Content Type wpstorelocator - if the BCT exists nothing happens
BorlabsCookieHelper()->addBlockedContentType(
'wpstorelocator',
'WP Store Locator',
'',
[],
'<div class="borlabs-cookie-bct bc-bct-iframe bc-bct-google-maps">
<p class="bc-thumbnail"><img src="%%thumbnail%%" alt="%%name%%"></p>
<div class="bc-text">
<p>' . _x( 'To protect your personal data, your connection to Google Maps has been blocked.<br>Click on <strong>Load map</strong> to unblock Google Maps.<br>By loading the map you accept the privacy policy of Google.<br>More information about Google\'s privacy policy can be found here <a href="https://policies.google.com/privacy?hl=en&gl=en" target="_blank" rel="nofollow">Google - Privacy & Terms</a> . ', 'Borlabs Cookie', 'wpsl' ) . '</p>
<p><label><input type="checkbox" name="unblockAll" value="1" checked> ' . _x( 'Do not block Google Maps in the future anymore.', 'Borlabs Cookie', 'wpsl' ) . '</label>
<a role="button" data-borlabs-cookie-unblock>' . _x( 'Load map', 'Borlabs Cookie', 'wpsl' ) . '</a></p>
</div>
</div>',
'',
'',
[
'responsiveIframe' => false,
],
true,
true
);
}
/**
* Remove the 'wpstorelocator' blocked content type
* from the Borlabs Cookie plugin.
*
* @since 2.2.22
*/
public function disable() {
if ( function_exists('BorlabsCookieHelper' ) ) {
BorlabsCookieHelper()->deleteBlockedContentType( 'wpstorelocator' );
}
}
/**
* modifyWPStoreLocatorContentBlockerBackwardsCompatibility function.
*
* @since 2.2.233
* @param mixed $id
* @param mixed $content
* @return void
*/
public function update_content_blocker_backwards_compatibility( $id, $content ) {
return $this->update_content_blocker($content);
}
/**
* modifyWPStoreLocatorContentBlocker function.
*
* @since 2.2.22
* @param mixed $content
* @param mixed $atts
* @return void
*/
public function update_content_blocker( $content, $atts = [] ) {
// Get settings of the Blocked Content Type
$wpsl_data = BorlabsCookieHelper()->getBlockedContentTypeDataByTypeId( 'wpstorelocator' );
// Workaround, fixed in newer versions of Borlabs Cookie
if ( !isset($wpsl_data['settings']['unblockAll'] ) ) {
$wpsl_data['settings']['unblockAll'] = false;
}
BorlabsCookieHelper()->updateBlockedContentTypeJavaScript(
'wpstorelocator',
'var myScriptTag = document.createElement("script"); myScriptTag.type = "text/javascript"; myScriptTag.src = "https://maps.google.com/maps/api/js' . wpsl_get_gmap_api_params( "browser_key" ) .'";jQuery("body").append(myScriptTag);',
'initWpslMap();',
$wpsl_data['settings']
);
// Default thumbnail
$thumbnail = BORLABS_COOKIE_PLUGIN_URL.'images/bct-google-maps.png';
// Get the title which was maybe set via title-attribute in a shortcode
$title = BorlabsCookieHelper()->getCurrentTitleOfBlockedContentType();
// If no title was set use the Blocked Content Type name as title
if ( empty( $title ) ) {
$title = $wpsl_data['name'];
}
// Replace text variables
if (!empty($atts)) {
foreach ($atts as $key => $value) {
$wpsl_data['previewHTML'] = str_replace('%%'.$key.'%%', $value, $wpsl_data['previewHTML']);
}
}
$wpsl_data['previewHTML'] = str_replace(
[
'%%name%%',
'%%thumbnail%%',
'%%privacy_policy_url%%',
],
[
$title,
$thumbnail,
$wpsl_data['privacyPolicyURL'],
],
$wpsl_data['previewHTML']
);
/* Return the HTML that displays the information, that the original content was blocked */
return $wpsl_data['previewHTML'];
}
}
new WPSL_Borlabs_Cookie();
} inc/class-templates.php 0000644 00000012627 15132722064 0011141 0 ustar 00 <?php
/**
* Handle the WPSL and Add-on templates
*
* @author Tijmen Smit
* @since 2.2.11
*/
if ( !defined( 'ABSPATH' ) ) exit;
if ( !class_exists( 'WPSL_Templates' ) ) {
class WPSL_Templates {
/**
* Get the list of available templates
*
* @since 2.2.11
* @param string $type The template type to return
* @return array|void
*/
public function get_template_list( $type = 'store_locator' ) {
$template_list = array();
// Add the WPSL templates or the add-on templates.
if ( $type == 'store_locator' ) {
$template_list['store_locator'] = wpsl_get_templates();
} else {
$template_list = apply_filters( 'wpsl_template_list', $template_list );
}
if ( isset( $template_list[$type] ) && !empty( $template_list[$type] ) ) {
return $template_list[$type];
}
}
/**
* Get the template details
*
* @since 2.2.11
* @param string $used_template The name of the template
* @param string $type The type of template data to load
* @return array $template_data The template data ( id, name, path )
*/
public function get_template_details( $used_template, $type = 'store_locator' ) {
$used_template = ( empty( $used_template ) ) ? 'default' : $used_template;
$templates = $this->get_template_list( $type );
$template_data = '';
$template_path = '';
if ( $templates ) {
// Grab the the correct template data from the available templates.
foreach ( $templates as $template ) {
if ( $used_template == $template['id'] ) {
$template_data = $template;
break;
}
}
}
// Old structure ( WPSL only ) was only the path, new structure ( add-ons ) expects the file name as well.
if ( isset( $template_data['path'] ) && isset( $template_data['file_name'] ) ) {
$template_path = $template_data['path'] . $template_data['file_name'];
} else if ( isset( $template_data['path'] ) ) {
$template_path = $template_data['path'];
}
// If no match exists, or the template file doesnt exist, then use the default template.
if ( !$template_data || ( !file_exists( $template_path ) ) ) {
$template_data = $this->get_default_template( $type );
// If no template can be loaded, then show a msg to the admin user.
if ( !$template_data && current_user_can( 'administrator' ) ) {
echo '<p>' . sprintf( __( 'No template found for %s', 'wpsl' ), $type ) . '</p>';
echo '<p>' . sprintf( __( 'Make sure you call the %sget_template_details%s function with the correct parameters.', 'wpsl' ), '<code>', '</code>' ) . '</p>';
}
}
return $template_data;
}
/**
* Locate the default template
*
* @since 2.2.11
* @param string $type The type of default template to return
* @return array $default The default template data
*/
public function get_default_template( $type = 'store_locator' ) {
$template_list = $this->get_template_list( $type );
$default = '';
if ( $template_list ) {
foreach ( $template_list as $template ) {
if ( $template['id'] == 'default' ) {
$default = $template;
break;
}
}
}
return $default;
}
/**
* Include the template file.
*
* @since 2.2.11
* @param array $args The template path details
* @param array $template_data The template data ( address, phone, fax etc ).
* @return string The location template.
*/
function get_template( $args, $template_data ) {
// Don't continue if not path and file name is set.
if ( !isset( $args['path'] ) || !isset( $args['file_name'] ) ) {
return;
}
ob_start();
include( $this->find_template_path( $args ) );
return ob_get_clean();
}
/**
* Locate the template file in either the
* theme folder or the plugin folder itself.
*
* @since 2.2.11
* @param array $args The template data
* @return string $template The path to the template.
*/
function find_template_path( $args ) {
// Look for the template in the theme folder.
$template = locate_template(
array( trailingslashit( 'wpsl-templates' ) . $args['file_name'], $args['file_name'] )
);
// If the template doesn't exist in the theme folder load the one from the plugin dir.
if ( !$template ) {
$template = $args['path'] . $args['file_name'];
}
return $template;
}
}
} inc/install.php 0000644 00000002721 15132722064 0007500 0 ustar 00 <?php
/**
* WPSL Install
*
* @author Tijmen Smit
* @since 2.0.0
*/
if ( !defined( 'ABSPATH' ) ) exit;
/**
* Run the install.
*
* @since 1.2.20
* @return void
*/
function wpsl_install( $network_wide ) {
global $wpdb;
if ( function_exists( 'is_multisite' ) && is_multisite() ) {
if ( $network_wide ) {
$blog_ids = $wpdb->get_col( "SELECT blog_id FROM $wpdb->blogs" );
foreach ( $blog_ids as $blog_id ) {
switch_to_blog( $blog_id );
wpsl_install_data();
}
restore_current_blog();
} else {
wpsl_install_data();
}
} else {
wpsl_install_data();
}
if ( function_exists( 'BorlabsCookieHelper' ) ) {
require_once( 'class-borlabs-cookie.php' );
$borlabs = New WPSL_Borlabs_Cookie();
$borlabs->enable();
}
}
/**
* Install the required data.
*
* @since 1.2.20
* @return void
*/
function wpsl_install_data() {
global $wpsl;
// Register the post type and flush the permalinks.
$wpsl->post_types->register_post_types();
flush_rewrite_rules();
// Create the default settings.
wpsl_set_default_settings();
// Set the correct version.
update_option( 'wpsl_version', WPSL_VERSION_NUM );
// Add user roles.
wpsl_add_roles();
// Add user capabilities.
wpsl_add_caps();
} inc/class-post-types.php 0000644 00000025750 15132722064 0011273 0 ustar 00 <?php
/**
* Store Locator custom post type.
*
* @author Tijmen Smit
* @since 2.0.0
*/
if ( !defined( 'ABSPATH' ) ) exit;
if ( !class_exists( 'WPSL_Post_Types' ) ) {
class WPSL_Post_Types {
/**
* Constructor
*/
public function __construct() {
add_action( 'init', array( $this, 'maybe_show_in_rest' ) );
add_action( 'init', array( $this, 'register_post_types' ), 10, 1 );
add_action( 'init', array( $this, 'register_taxonomies' ), 10, 1 );
add_action( 'manage_wpsl_stores_posts_custom_column', array( $this, 'custom_columns' ), 10, 2 );
add_filter( 'enter_title_here', array( $this, 'change_default_title' ) );
add_filter( 'manage_edit-wpsl_stores_columns', array( $this, 'edit_columns' ) );
add_filter( 'manage_edit-wpsl_stores_sortable_columns', array( $this, 'sortable_columns' ) );
add_filter( 'request', array( $this, 'sort_columns' ) );
}
/**
* Check if we need to set 'show_in_rest' to true/false,
* and thereby enabling the REST API.
*
* This needs to be set to true for
* Gutenberg to be enabled.
*
* Full REST API support will come in the 3.0 update.
*
* @since 2.2.19
* @return bool
*/
public function maybe_show_in_rest() {
global $wp_version;
return ( version_compare( $wp_version, '5', '>=' ) ) ? true : false;
}
/**
* Register the WPSL post type.
*
* @since 2.0.0
* @return void
*/
public function register_post_types() {
global $wpsl_settings;
// Enable permalinks for the post type?
if ( isset( $wpsl_settings['permalinks'] ) && $wpsl_settings['permalinks'] ) {
$public = true;
$exclude_from_search = false;
$rewrite = array( 'slug' => $wpsl_settings['permalink_slug'] );
if ( $wpsl_settings['permalink_remove_front'] ) {
$rewrite['with_front'] = false;
}
} else {
$public = false;
$exclude_from_search = true;
$rewrite = false;
}
// The labels for the wpsl_stores post type.
$labels = apply_filters( 'wpsl_post_type_labels', array(
'name' => __( 'Store Locator', 'wpsl' ),
'all_items' => __( 'All Stores', 'wpsl' ),
'singular_name' => __( 'Store', 'wpsl' ),
'add_new' => __( 'New Store', 'wpsl' ),
'add_new_item' => __( 'Add New Store', 'wpsl' ),
'edit_item' => __( 'Edit Store', 'wpsl' ),
'new_item' => __( 'New Store', 'wpsl' ),
'view_item' => __( 'View Stores', 'wpsl' ),
'search_items' => __( 'Search Stores', 'wpsl' ),
'not_found' => __( 'No Stores found', 'wpsl' ),
'not_found_in_trash' => __( 'No Stores found in trash', 'wpsl' ),
)
);
// The arguments for the wpsl_stores post type.
$args = apply_filters( 'wpsl_post_type_args', array(
'labels' => $labels,
'public' => $public,
'exclude_from_search' => $exclude_from_search,
'show_ui' => true,
'menu_position' => apply_filters( 'wpsl_post_type_menu_position', null ),
'capability_type' => 'store',
'map_meta_cap' => true,
'rewrite' => $rewrite,
'query_var' => 'wpsl_stores',
'supports' => array( 'title', 'editor', 'author', 'excerpt', 'revisions', 'thumbnail' ),
'show_in_rest' => $this->maybe_show_in_rest()
)
);
register_post_type( 'wpsl_stores', $args );
}
/**
* Register the WPSL custom taxonomy.
*
* @since 2.0.0
* @return void
*/
public function register_taxonomies() {
global $wpsl_settings;
// Enable permalinks for the taxonomy?
if ( isset( $wpsl_settings['permalinks'] ) && $wpsl_settings['permalinks'] ) {
$public = true;
$rewrite = array( 'slug' => $wpsl_settings['category_slug'] );
} else {
$public = false;
$rewrite = false;
}
$labels = array(
'name' => __( 'Store Categories', 'wpsl' ),
'singular_name' => __( 'Store Category', 'wpsl' ),
'search_items' => __( 'Search Store Categories', 'wpsl' ),
'all_items' => __( 'All Store Categories', 'wpsl' ),
'parent_item' => __( 'Parent Store Category', 'wpsl' ),
'parent_item_colon' => __( 'Parent Store Category:', 'wpsl' ),
'edit_item' => __( 'Edit Store Category', 'wpsl' ),
'update_item' => __( 'Update Store Category', 'wpsl' ),
'add_new_item' => __( 'Add New Store Category', 'wpsl' ),
'new_item_name' => __( 'New Store Category Name', 'wpsl' ),
'menu_name' => __( 'Store Categories', 'wpsl' ),
);
$args = apply_filters( 'wpsl_store_category_args', array(
'labels' => $labels,
'public' => $public,
'hierarchical' => true,
'show_ui' => true,
'show_admin_column' => true,
'update_count_callback' => '_update_post_term_count',
'query_var' => true,
'rewrite' => $rewrite,
'show_in_rest' => $this->maybe_show_in_rest()
)
);
register_taxonomy( 'wpsl_store_category', 'wpsl_stores', $args );
}
/**
* Change the default "Enter title here" placeholder.
*
* @since 2.0.0
* @param string $title The default title placeholder
* @return string $title The new title placeholder
*/
public function change_default_title( $title ) {
$screen = get_current_screen();
if ( $screen->post_type == 'wpsl_stores' ) {
$title = __( 'Enter store title here', 'wpsl' );
}
return $title;
}
/**
* Add new columns to the store list table.
*
* @since 2.0.0
* @param array $columns The default columns
* @return array $columns Updated column list
*/
public function edit_columns( $columns ) {
$columns['address'] = __( 'Address', 'wpsl' );
$columns['city'] = __( 'City', 'wpsl' );
$columns['state'] = __( 'State', 'wpsl' );
$columns['zip'] = __( 'Zip', 'wpsl' );
return $columns;
}
/**
* Show the correct store content in the correct custom column.
*
* @since 2.0.0
* @param string $column The column name
* @param int $post_id The post id
* @return void
*/
public function custom_columns( $column, $post_id ) {
switch ( $column ) {
case 'address':
echo esc_html( get_post_meta( $post_id, 'wpsl_address', true ) );
break;
case 'city':
echo esc_html( get_post_meta( $post_id, 'wpsl_city', true ) );
break;
case 'state':
echo esc_html( get_post_meta( $post_id, 'wpsl_state', true ) );
break;
case 'zip':
echo esc_html( get_post_meta( $post_id, 'wpsl_zip', true ) );
break;
}
}
/**
* Define the columns that are sortable.
*
* @since 2.0.0
* @param array $columns List of sortable columns
* @return array
*/
public function sortable_columns( $columns ) {
$custom = array(
'address' => 'wpsl_address',
'city' => 'wpsl_city',
'state' => 'wpsl_state',
'zip' => 'wpsl_zip'
);
return wp_parse_args( $custom, $columns );
}
/**
* Set the correct column sort parameters.
*
* @since 2.0.0
* @param array $vars Column sorting parameters
* @return array $vars The column sorting parameters inc the correct orderby and wpsl meta_key
*/
public function sort_columns( $vars ) {
if ( isset( $vars['post_type'] ) && $vars['post_type'] == 'wpsl_stores' ) {
if ( isset( $vars['orderby'] ) ) {
if ( $vars['orderby'] === 'wpsl_address' ) {
$vars = array_merge( $vars, array(
'meta_key' => 'wpsl_address',
'orderby' => 'meta_value'
) );
}
if ( $vars['orderby'] === 'wpsl_city' ) {
$vars = array_merge( $vars, array(
'meta_key' => 'wpsl_city',
'orderby' => 'meta_value'
) );
}
if ( $vars['orderby'] === 'wpsl_state' ) {
$vars = array_merge( $vars, array(
'meta_key' => 'wpsl_state',
'orderby' => 'meta_value'
) );
}
if ( $vars['orderby'] === 'wpsl_zip' ) {
$vars = array_merge( $vars, array(
'meta_key' => 'wpsl_zip',
'orderby' => 'meta_value'
) );
}
}
}
return $vars;
}
}
} inc/class-i18n.php 0000644 00000012750 15132722064 0007717 0 ustar 00 <?php
/**
* i18n class
*
* @author Tijmen Smit
* @since 2.0.0
*/
if ( !defined( 'ABSPATH' ) ) exit;
if ( !class_exists( 'WPSL_i18n' ) ) {
class WPSL_i18n {
private $wpml_active = null;
private $qtrans_active = null;
/**
* Class constructor
*/
function __construct() {
add_action( 'plugins_loaded', array( $this, 'load_plugin_textdomain' ) );
}
/**
* Load the translations from the language folder
*
* @since 2.0.0
* @return void
*/
public function load_plugin_textdomain() {
$domain = 'wpsl';
$locale = apply_filters( 'plugin_locale', get_locale(), $domain );
// Load the language file from the /wp-content/languages/wp-store-locator folder, custom + update proof translations.
load_textdomain( $domain, WP_LANG_DIR . '/wp-store-locator/' . $domain . '-' . $locale . '.mo' );
// Load the language file from the /wp-content/plugins/wp-store-locator/languages/ folder.
load_plugin_textdomain( $domain, false, dirname( WPSL_BASENAME ) . '/languages/' );
}
/**
* Check if WPML is active
*
* @since 2.0.0
* @return boolean|null
*/
public function wpml_exists() {
if ( $this->wpml_active == null ) {
$this->wpml_active = function_exists( 'icl_register_string' );
}
return $this->wpml_active;
}
/**
* Check if a qTranslate compatible plugin is active.
*
* @since 2.0.0
* @return boolean|null
*/
public function qtrans_exists() {
if ( $this->qtrans_active == null ) {
$this->qtrans_active = ( function_exists( 'qtrans_useCurrentLanguageIfNotFoundUseDefaultLanguage' ) || function_exists( 'qtranxf_useCurrentLanguageIfNotFoundUseDefaultLanguage' ) );
}
return $this->qtrans_active;
}
/**
* See if there is a translated page available for the provided store ID.
*
* @since 2.0.0
* @see https://wpml.org/documentation/support/creating-multilingual-wordpress-themes/language-dependent-ids/#2
* @param string $store_id
* @return string empty or the id of the translated store
*/
public function maybe_get_wpml_id( $store_id ) {
$return_original_id = apply_filters( 'wpsl_return_original_wpml_id', true );
// icl_object_id is deprecated as of 3.2
if ( defined( 'ICL_SITEPRESS_VERSION' ) && version_compare( ICL_SITEPRESS_VERSION, 3.2, '>=' ) ) {
$translated_id = apply_filters( 'wpml_object_id', $store_id, 'wpsl_stores', $return_original_id, ICL_LANGUAGE_CODE );
} else {
$translated_id = icl_object_id( $store_id, 'wpsl_stores', $return_original_id, ICL_LANGUAGE_CODE );
}
// If '$return_original_id' is set to false, NULL is returned if no translation exists.
if ( is_null( $translated_id ) ) {
$translated_id = '';
}
return $translated_id;
}
/**
* Get the correct translation.
*
* Return the translated text from WPML or the translation
* that was set on the settings page.
*
* @since 2.0.0
* @param string $name The name of the translated string
* @param string $text The text of the translated string
* @return string $translation The translation
*/
public function get_translation( $name, $text ) {
global $wpsl_settings;
if ( defined( 'WPML_ST_VERSION' ) ) {
$translation = $text;
} elseif ( defined( 'POLYLANG_VERSION' ) && defined( 'POLYLANG_DIR' ) ) {
if ( ! function_exists( 'pll__' ) ) {
require_once POLYLANG_DIR . '/include/api.php';
}
$translation = pll__( $text );
} else {
$translation = stripslashes( $wpsl_settings[$name] );
}
return $translation;
}
/**
* If a multilingual plugin like WPML or qTranslate X is active
* we return the active language code.
*
* @since 2.0.0
* @return string Empty or the current language code
*/
public function check_multilingual_code() {
$language_code = '';
if ( $this->wpml_exists() && defined( 'ICL_LANGUAGE_CODE' ) ) {
$language_code = ICL_LANGUAGE_CODE;
} else if ( $this->qtrans_exists() ) {
if ( function_exists( 'qtranxf_getLanguage' ) ) {
$language_code = qtranxf_getLanguage();
} else if ( function_exists( 'qtrans_getLanguage' ) ) {
$language_code = qtrans_getLanguage();
}
}
return $language_code;
}
}
new WPSL_i18n();
} frontend/underscore-functions.php 0000644 00000033415 15132722064 0013263 0 ustar 00 <?php
/**
* Create the store data templates.
*
* The templates are created in JS with _.template, see http://underscorejs.org/#template
*
* @since 2.0.0
* @param string $template The type of template we need to create
* @return void
*/
function wpsl_create_underscore_templates( $template ) {
global $wpsl_settings, $wpsl;
if ( $template == 'wpsl_store_locator' ) {
?>
<script id="wpsl-info-window-template" type="text/template">
<?php
$info_window_template = '<div data-store-id="<%= id %>" class="wpsl-info-window">' . "\r\n";
$info_window_template .= "\t\t" . '<p>' . "\r\n";
$info_window_template .= "\t\t\t" . wpsl_store_header_template() . "\r\n"; // Check which header format we use
$info_window_template .= "\t\t\t" . '<span><%= address %></span>' . "\r\n";
$info_window_template .= "\t\t\t" . '<% if ( address2 ) { %>' . "\r\n";
$info_window_template .= "\t\t\t" . '<span><%= address2 %></span>' . "\r\n";
$info_window_template .= "\t\t\t" . '<% } %>' . "\r\n";
$info_window_template .= "\t\t\t" . '<span>' . wpsl_address_format_placeholders() . '</span>' . "\r\n"; // Use the correct address format
$info_window_template .= "\t\t" . '</p>' . "\r\n";
$info_window_template .= "\t\t" . '<% if ( phone ) { %>' . "\r\n";
$info_window_template .= "\t\t" . '<span><strong>' . esc_html( $wpsl->i18n->get_translation( 'phone_label', __( 'Phone', 'wpsl' ) ) ) . '</strong>: <%= formatPhoneNumber( phone ) %></span>' . "\r\n";
$info_window_template .= "\t\t" . '<% } %>' . "\r\n";
$info_window_template .= "\t\t" . '<% if ( fax ) { %>' . "\r\n";
$info_window_template .= "\t\t" . '<span><strong>' . esc_html( $wpsl->i18n->get_translation( 'fax_label', __( 'Fax', 'wpsl' ) ) ) . '</strong>: <%= fax %></span>' . "\r\n";
$info_window_template .= "\t\t" . '<% } %>' . "\r\n";
$info_window_template .= "\t\t" . '<% if ( email ) { %>' . "\r\n";
$info_window_template .= "\t\t" . '<span><strong>' . esc_html( $wpsl->i18n->get_translation( 'email_label', __( 'Email', 'wpsl' ) ) ) . '</strong>: <%= formatEmail( email ) %></span>' . "\r\n";
$info_window_template .= "\t\t" . '<% } %>' . "\r\n";
$info_window_template .= "\t\t" . '<%= createInfoWindowActions( id ) %>' . "\r\n";
$info_window_template .= "\t" . '</div>';
echo apply_filters( 'wpsl_info_window_template', $info_window_template . "\n" );
?>
</script>
<script id="wpsl-listing-template" type="text/template">
<?php
$listing_template = '<li data-store-id="<%= id %>">' . "\r\n";
$listing_template .= "\t\t" . '<div class="wpsl-store-location">' . "\r\n";
$listing_template .= "\t\t\t" . '<p><%= thumb %>' . "\r\n";
$listing_template .= "\t\t\t\t" . wpsl_store_header_template( 'listing' ) . "\r\n"; // Check which header format we use
$listing_template .= "\t\t\t\t" . '<span class="wpsl-street"><%= address %></span>' . "\r\n";
$listing_template .= "\t\t\t\t" . '<% if ( address2 ) { %>' . "\r\n";
$listing_template .= "\t\t\t\t" . '<span class="wpsl-street"><%= address2 %></span>' . "\r\n";
$listing_template .= "\t\t\t\t" . '<% } %>' . "\r\n";
$listing_template .= "\t\t\t\t" . '<span>' . wpsl_address_format_placeholders() . '</span>' . "\r\n"; // Use the correct address format
if ( !$wpsl_settings['hide_country'] ) {
$listing_template .= "\t\t\t\t" . '<span class="wpsl-country"><%= country %></span>' . "\r\n";
}
$listing_template .= "\t\t\t" . '</p>' . "\r\n";
// Show the phone, fax or email data if they exist.
if ( $wpsl_settings['show_contact_details'] ) {
$listing_template .= "\t\t\t" . '<p class="wpsl-contact-details">' . "\r\n";
$listing_template .= "\t\t\t" . '<% if ( phone ) { %>' . "\r\n";
$listing_template .= "\t\t\t" . '<span><strong>' . esc_html( $wpsl->i18n->get_translation( 'phone_label', __( 'Phone', 'wpsl' ) ) ) . '</strong>: <%= formatPhoneNumber( phone ) %></span>' . "\r\n";
$listing_template .= "\t\t\t" . '<% } %>' . "\r\n";
$listing_template .= "\t\t\t" . '<% if ( fax ) { %>' . "\r\n";
$listing_template .= "\t\t\t" . '<span><strong>' . esc_html( $wpsl->i18n->get_translation( 'fax_label', __( 'Fax', 'wpsl' ) ) ) . '</strong>: <%= fax %></span>' . "\r\n";
$listing_template .= "\t\t\t" . '<% } %>' . "\r\n";
$listing_template .= "\t\t\t" . '<% if ( email ) { %>' . "\r\n";
$listing_template .= "\t\t\t" . '<span><strong>' . esc_html( $wpsl->i18n->get_translation( 'email_label', __( 'Email', 'wpsl' ) ) ) . '</strong>: <%= formatEmail( email ) %></span>' . "\r\n";
$listing_template .= "\t\t\t" . '<% } %>' . "\r\n";
$listing_template .= "\t\t\t" . '</p>' . "\r\n";
}
$listing_template .= "\t\t\t" . wpsl_more_info_template() . "\r\n"; // Check if we need to show the 'More Info' link and info
$listing_template .= "\t\t" . '</div>' . "\r\n";
$listing_template .= "\t\t" . '<div class="wpsl-direction-wrap">' . "\r\n";
if ( !$wpsl_settings['hide_distance'] ) {
$listing_template .= "\t\t\t" . '<%= distance %> ' . esc_html( wpsl_get_distance_unit() ) . '' . "\r\n";
}
$listing_template .= "\t\t\t" . '<%= createDirectionUrl() %>' . "\r\n";
$listing_template .= "\t\t" . '</div>' . "\r\n";
$listing_template .= "\t" . '</li>';
echo apply_filters( 'wpsl_listing_template', $listing_template . "\n" );
?>
</script>
<?php
} else {
?>
<script id="wpsl-cpt-info-window-template" type="text/template">
<?php
$cpt_info_window_template = '<div class="wpsl-info-window">' . "\r\n";
$cpt_info_window_template .= "\t\t" . '<p class="wpsl-no-margin">' . "\r\n";
$cpt_info_window_template .= "\t\t\t" . wpsl_store_header_template( 'wpsl_map' ) . "\r\n";
$cpt_info_window_template .= "\t\t\t" . '<span><%= address %></span>' . "\r\n";
$cpt_info_window_template .= "\t\t\t" . '<% if ( address2 ) { %>' . "\r\n";
$cpt_info_window_template .= "\t\t\t" . '<span><%= address2 %></span>' . "\r\n";
$cpt_info_window_template .= "\t\t\t" . '<% } %>' . "\r\n";
$cpt_info_window_template .= "\t\t\t" . '<span>' . wpsl_address_format_placeholders() . '</span>' . "\r\n"; // Use the correct address format
if ( !$wpsl_settings['hide_country'] ) {
$cpt_info_window_template .= "\t\t\t" . '<span class="wpsl-country"><%= country %></span>' . "\r\n";
}
$cpt_info_window_template .= "\t\t" . '</p>' . "\r\n";
$cpt_info_window_template .= "\t" . '</div>';
echo apply_filters( 'wpsl_cpt_info_window_template', $cpt_info_window_template . "\n" );
?>
</script>
<?php
}
}
/**
* Create the more info template.
*
* @since 2.0.0
* @return string $more_info_template The template that is used to show the "More info" content
*/
function wpsl_more_info_template() {
global $wpsl_settings, $wpsl;
if ( $wpsl_settings['more_info'] ) {
$more_info_url = '#';
if ( $wpsl_settings['template_id'] == 'default' && $wpsl_settings['more_info_location'] == 'info window' ) {
$more_info_url = '#wpsl-search-wrap';
}
if ( $wpsl_settings['more_info_location'] == 'store listings' ) {
$more_info_template = '<% if ( !_.isEmpty( phone ) || !_.isEmpty( fax ) || !_.isEmpty( email ) ) { %>' . "\r\n";
$more_info_template .= "\t\t\t" . '<p><a class="wpsl-store-details wpsl-store-listing" href="#wpsl-id-<%= id %>">' . esc_html( $wpsl->i18n->get_translation( 'more_label', __( 'More info', 'wpsl' ) ) ) . '</a></p>' . "\r\n";
$more_info_template .= "\t\t\t" . '<div id="wpsl-id-<%= id %>" class="wpsl-more-info-listings">' . "\r\n";
$more_info_template .= "\t\t\t\t" . '<% if ( description ) { %>' . "\r\n";
$more_info_template .= "\t\t\t\t" . '<%= description %>' . "\r\n";
$more_info_template .= "\t\t\t\t" . '<% } %>' . "\r\n";
if ( !$wpsl_settings['show_contact_details'] ) {
$more_info_template .= "\t\t\t\t" . '<p>' . "\r\n";
$more_info_template .= "\t\t\t\t" . '<% if ( phone ) { %>' . "\r\n";
$more_info_template .= "\t\t\t\t" . '<span><strong>' . esc_html( $wpsl->i18n->get_translation( 'phone_label', __( 'Phone', 'wpsl' ) ) ) . '</strong>: <%= formatPhoneNumber( phone ) %></span>' . "\r\n";
$more_info_template .= "\t\t\t\t" . '<% } %>' . "\r\n";
$more_info_template .= "\t\t\t\t" . '<% if ( fax ) { %>' . "\r\n";
$more_info_template .= "\t\t\t\t" . '<span><strong>' . esc_html( $wpsl->i18n->get_translation( 'fax_label', __( 'Fax', 'wpsl' ) ) ) . '</strong>: <%= fax %></span>' . "\r\n";
$more_info_template .= "\t\t\t\t" . '<% } %>' . "\r\n";
$more_info_template .= "\t\t\t\t" . '<% if ( email ) { %>' . "\r\n";
$more_info_template .= "\t\t\t\t" . '<span><strong>' . esc_html( $wpsl->i18n->get_translation( 'email_label', __( 'Email', 'wpsl' ) ) ) . '</strong>: <%= formatEmail( email ) %></span>' . "\r\n";
$more_info_template .= "\t\t\t\t" . '<% } %>' . "\r\n";
$more_info_template .= "\t\t\t\t" . '</p>' . "\r\n";
}
if ( !$wpsl_settings['hide_hours'] ) {
$more_info_template .= "\t\t\t\t" . '<% if ( hours ) { %>' . "\r\n";
$more_info_template .= "\t\t\t\t" . '<div class="wpsl-store-hours"><strong>' . esc_html( $wpsl->i18n->get_translation( 'hours_label', __( 'Hours', 'wpsl' ) ) ) . '</strong><%= hours %></div>' . "\r\n";
$more_info_template .= "\t\t\t\t" . '<% } %>' . "\r\n";
}
$more_info_template .= "\t\t\t" . '</div>' . "\r\n";
$more_info_template .= "\t\t\t" . '<% } %>';
} else {
$more_info_template = '<p><a class="wpsl-store-details" href="' . $more_info_url . '">' . esc_html( $wpsl->i18n->get_translation( 'more_label', __( 'More info', 'wpsl' ) ) ) . '</a></p>';
}
return apply_filters( 'wpsl_more_info_template', $more_info_template );
}
}
/**
* Create the store header template.
*
* @since 2.0.0
* @param string $location The location where the header is shown ( info_window / listing / wpsl_map shortcode )
* @return string $header_template The template for the store header
*/
function wpsl_store_header_template( $location = 'info_window' ) {
global $wpsl_settings;
if ( $wpsl_settings['new_window'] ) {
$new_window = ' target="_blank"';
} else {
$new_window = '';
}
/*
* To keep the code readable in the HTML source we ( unfortunately ) need to adjust the
* amount of tabs in front of it based on the location were it is shown.
*/
if ( $location == 'listing') {
$tab = "\t\t\t\t";
} else {
$tab = "\t\t\t";
}
if ( $wpsl_settings['permalinks'] ) {
/**
* It's possible the permalinks are enabled, but not included in the location data on
* pages where the [wpsl_map] shortcode is used.
*
* So we need to check for undefined, which isn't necessary in all other cases.
*/
if ( $location == 'wpsl_map') {
$header_template = '<% if ( typeof permalink !== "undefined" ) { %>' . "\r\n";
$header_template .= $tab . '<strong><a' . $new_window . ' href="<%= permalink %>"><%= store %></a></strong>' . "\r\n";
$header_template .= $tab . '<% } else { %>' . "\r\n";
$header_template .= $tab . '<strong><%= store %></strong>' . "\r\n";
$header_template .= $tab . '<% } %>';
} else {
$header_template = '<strong><a' . $new_window . ' href="<%= permalink %>"><%= store %></a></strong>';
}
} else {
$header_template = '<% if ( wpslSettings.storeUrl == 1 && url ) { %>' . "\r\n";
$header_template .= $tab . '<strong><a' . $new_window . ' href="<%= url %>"><%= store %></a></strong>' . "\r\n";
$header_template .= $tab . '<% } else { %>' . "\r\n";
$header_template .= $tab . '<strong><%= store %></strong>' . "\r\n";
$header_template .= $tab . '<% } %>';
}
return apply_filters( 'wpsl_store_header_template', $header_template );
}
/**
* Create the address placeholders based on the structure defined on the settings page.
*
* @since 2.0.0
* @return string $address_placeholders A list of address placeholders in the correct order
*/
function wpsl_address_format_placeholders() {
global $wpsl_settings;
$address_format = explode( '_', $wpsl_settings['address_format'] );
$placeholders = '';
$part_count = count( $address_format ) - 1;
$i = 0;
foreach ( $address_format as $address_part ) {
if ( $address_part != 'comma' ) {
/*
* Don't add a space after the placeholder if the next part
* is going to be a comma or if it is the last part.
*/
if ( $i == $part_count || $address_format[$i + 1] == 'comma' ) {
$space = '';
} else {
$space = ' ';
}
$placeholders .= '<%= ' . $address_part . ' %>' . $space;
} else {
$placeholders .= ', ';
}
$i++;
}
return $placeholders;
} frontend/templates/default.php 0000644 00000007003 15132722064 0012520 0 ustar 00 <?php
global $wpsl_settings, $wpsl;
$output = $this->get_custom_css();
$autoload_class = ( !$wpsl_settings['autoload'] ) ? 'class="wpsl-not-loaded"' : '';
$output .= '<div id="wpsl-wrap">' . "\r\n";
$output .= "\t" . '<div class="wpsl-search wpsl-clearfix ' . $this->get_css_classes() . '">' . "\r\n";
$output .= "\t\t" . '<div id="wpsl-search-wrap">' . "\r\n";
$output .= "\t\t\t" . '<form autocomplete="off">' . "\r\n";
$output .= "\t\t\t" . '<div class="wpsl-input">' . "\r\n";
$output .= "\t\t\t\t" . '<div><label for="wpsl-search-input">' . esc_html( $wpsl->i18n->get_translation( 'search_label', __( 'Your location', 'wpsl' ) ) ) . '</label></div>' . "\r\n";
$output .= "\t\t\t\t" . '<input id="wpsl-search-input" type="text" value="' . apply_filters( 'wpsl_search_input', '' ) . '" name="wpsl-search-input" placeholder="" aria-required="true" />' . "\r\n";
$output .= "\t\t\t" . '</div>' . "\r\n";
if ( $wpsl_settings['radius_dropdown'] || $wpsl_settings['results_dropdown'] ) {
$output .= "\t\t\t" . '<div class="wpsl-select-wrap">' . "\r\n";
if ( $wpsl_settings['radius_dropdown'] ) {
$output .= "\t\t\t\t" . '<div id="wpsl-radius">' . "\r\n";
$output .= "\t\t\t\t\t" . '<label for="wpsl-radius-dropdown">' . esc_html( $wpsl->i18n->get_translation( 'radius_label', __( 'Search radius', 'wpsl' ) ) ) . '</label>' . "\r\n";
$output .= "\t\t\t\t\t" . '<select id="wpsl-radius-dropdown" class="wpsl-dropdown" name="wpsl-radius">' . "\r\n";
$output .= "\t\t\t\t\t\t" . $this->get_dropdown_list( 'search_radius' ) . "\r\n";
$output .= "\t\t\t\t\t" . '</select>' . "\r\n";
$output .= "\t\t\t\t" . '</div>' . "\r\n";
}
if ( $wpsl_settings['results_dropdown'] ) {
$output .= "\t\t\t\t" . '<div id="wpsl-results">' . "\r\n";
$output .= "\t\t\t\t\t" . '<label for="wpsl-results-dropdown">' . esc_html( $wpsl->i18n->get_translation( 'results_label', __( 'Results', 'wpsl' ) ) ) . '</label>' . "\r\n";
$output .= "\t\t\t\t\t" . '<select id="wpsl-results-dropdown" class="wpsl-dropdown" name="wpsl-results">' . "\r\n";
$output .= "\t\t\t\t\t\t" . $this->get_dropdown_list( 'max_results' ) . "\r\n";
$output .= "\t\t\t\t\t" . '</select>' . "\r\n";
$output .= "\t\t\t\t" . '</div>' . "\r\n";
}
$output .= "\t\t\t" . '</div>' . "\r\n";
}
if ( $this->use_category_filter() ) {
$output .= $this->create_category_filter();
}
$output .= "\t\t\t\t" . '<div class="wpsl-search-btn-wrap"><input id="wpsl-search-btn" type="submit" value="' . esc_attr( $wpsl->i18n->get_translation( 'search_btn_label', __( 'Search', 'wpsl' ) ) ) . '"></div>' . "\r\n";
$output .= "\t\t" . '</form>' . "\r\n";
$output .= "\t\t" . '</div>' . "\r\n";
$output .= "\t" . '</div>' . "\r\n";
$output .= "\t" . '<div id="wpsl-gmap" class="wpsl-gmap-canvas"></div>' . "\r\n";
$output .= "\t" . '<div id="wpsl-result-list">' . "\r\n";
$output .= "\t\t" . '<div id="wpsl-stores" '. $autoload_class .'>' . "\r\n";
$output .= "\t\t\t" . '<ul></ul>' . "\r\n";
$output .= "\t\t" . '</div>' . "\r\n";
$output .= "\t\t" . '<div id="wpsl-direction-details">' . "\r\n";
$output .= "\t\t\t" . '<ul></ul>' . "\r\n";
$output .= "\t\t" . '</div>' . "\r\n";
$output .= "\t" . '</div>' . "\r\n";
if ( $wpsl_settings['show_credits'] ) {
$output .= "\t" . '<div class="wpsl-provided-by">'. sprintf( __( "Search provided by %sWP Store Locator%s", "wpsl" ), "<a target='_blank' href='https://wpstorelocator.co'>", "</a>" ) .'</div>' . "\r\n";
}
$output .= '</div>' . "\r\n";
return $output; frontend/templates/store-listings-below.php 0000644 00000007535 15132722064 0015202 0 ustar 00 <?php
global $wpsl_settings, $wpsl;
$output = $this->get_custom_css();
$autoload_class = ( !$wpsl_settings['autoload'] ) ? 'class="wpsl-not-loaded"' : '';
$output .= '<div id="wpsl-wrap" class="wpsl-store-below">' . "\r\n";
$output .= "\t" . '<div class="wpsl-search wpsl-clearfix ' . $this->get_css_classes() . '">' . "\r\n";
$output .= "\t\t" . '<div id="wpsl-search-wrap">' . "\r\n";
$output .= "\t\t\t" . '<form autocomplete="off">' . "\r\n";
$output .= "\t\t\t" . '<div class="wpsl-input">' . "\r\n";
$output .= "\t\t\t\t" . '<div><label for="wpsl-search-input">' . esc_html( $wpsl->i18n->get_translation( 'search_label', __( 'Your location', 'wpsl' ) ) ) . '</label></div>' . "\r\n";
$output .= "\t\t\t\t" . '<input id="wpsl-search-input" type="text" value="' . apply_filters( 'wpsl_search_input', '' ) . '" name="wpsl-search-input" placeholder="" aria-required="true" />' . "\r\n";
$output .= "\t\t\t" . '</div>' . "\r\n";
if ( $wpsl_settings['radius_dropdown'] || $wpsl_settings['results_dropdown'] ) {
$output .= "\t\t\t" . '<div class="wpsl-select-wrap">' . "\r\n";
if ( $wpsl_settings['radius_dropdown'] ) {
$output .= "\t\t\t\t" . '<div id="wpsl-radius">' . "\r\n";
$output .= "\t\t\t\t\t" . '<label for="wpsl-radius-dropdown">' . esc_html( $wpsl->i18n->get_translation( 'radius_label', __( 'Search radius', 'wpsl' ) ) ) . '</label>' . "\r\n";
$output .= "\t\t\t\t\t" . '<select id="wpsl-radius-dropdown" class="wpsl-dropdown" name="wpsl-radius">' . "\r\n";
$output .= "\t\t\t\t\t\t" . $this->get_dropdown_list( 'search_radius' ) . "\r\n";
$output .= "\t\t\t\t\t" . '</select>' . "\r\n";
$output .= "\t\t\t\t" . '</div>' . "\r\n";
}
if ( $wpsl_settings['results_dropdown'] ) {
$output .= "\t\t\t\t" . '<div id="wpsl-results">' . "\r\n";
$output .= "\t\t\t\t\t" . '<label for="wpsl-results-dropdown">' . esc_html( $wpsl->i18n->get_translation( 'results_label', __( 'Results', 'wpsl' ) ) ) . '</label>' . "\r\n";
$output .= "\t\t\t\t\t" . '<select id="wpsl-results-dropdown" class="wpsl-dropdown" name="wpsl-results">' . "\r\n";
$output .= "\t\t\t\t\t\t" . $this->get_dropdown_list( 'max_results' ) . "\r\n";
$output .= "\t\t\t\t\t" . '</select>' . "\r\n";
$output .= "\t\t\t\t" . '</div>' . "\r\n";
}
$output .= "\t\t\t" . '</div>' . "\r\n";
}
if ( $this->use_category_filter() ) {
$output .= $this->create_category_filter();
}
$output .= "\t\t\t\t" . '<div class="wpsl-search-btn-wrap"><input id="wpsl-search-btn" type="submit" value="' . esc_attr( $wpsl->i18n->get_translation( 'search_btn_label', __( 'Search', 'wpsl' ) ) ) . '"></div>' . "\r\n";
$output .= "\t\t" . '</form>' . "\r\n";
$output .= "\t\t" . '</div>' . "\r\n";
$output .= "\t" . '</div>' . "\r\n";
if ( $wpsl_settings['reset_map'] ) {
$output .= "\t" . '<div class="wpsl-gmap-wrap">' . "\r\n";
$output .= "\t\t" . '<div id="wpsl-gmap" class="wpsl-gmap-canvas"></div>' . "\r\n";
$output .= "\t" . '</div>' . "\r\n";
} else {
$output .= "\t" . '<div id="wpsl-gmap" class="wpsl-gmap-canvas"></div>' . "\r\n";
}
$output .= "\t" . '<div id="wpsl-result-list">' . "\r\n";
$output .= "\t\t" . '<div id="wpsl-stores" '. $autoload_class .'>' . "\r\n";
$output .= "\t\t\t" . '<ul></ul>' . "\r\n";
$output .= "\t\t" . '</div>' . "\r\n";
$output .= "\t\t" . '<div id="wpsl-direction-details">' . "\r\n";
$output .= "\t\t\t" . '<ul></ul>' . "\r\n";
$output .= "\t\t" . '</div>' . "\r\n";
$output .= "\t" . '</div>' . "\r\n";
if ( $wpsl_settings['show_credits'] ) {
$output .= "\t" . '<div class="wpsl-provided-by">'. sprintf( __( "Search provided by %sWP Store Locator%s", "wpsl" ), "<a target='_blank' href='https://wpstorelocator.co'>", "</a>" ) .'</div>' . "\r\n";
}
$output .= '</div>' . "\r\n";
return $output; frontend/class-frontend.php 0000644 00000242245 15132722064 0012031 0 ustar 00 <?php
/**
* Frontend class
*
* @author Tijmen Smit
* @since 1.0.0
*/
if ( !defined( 'ABSPATH' ) ) exit;
if ( !class_exists( 'WPSL_Frontend' ) ) {
/**
* Handle the frontend of the store locator
*
* @since 1.0.0
*/
class WPSL_Frontend {
/**
* Keep track which scripts we need to load
*
* @since 2.0.0
*/
private $load_scripts = array();
/**
* Keep track of the amount of maps on the page
*
* @since 2.0.0
*/
private static $map_count = 0;
/*
* Holds the shortcode atts for the [wpsl] shortcode.
*
* Used to overwrite the settings just before
* they are send to wp_localize_script.
*
* @since 2.1.1
*/
public $sl_shortcode_atts;
private $store_map_data = array();
/**
* Class constructor
*/
public function __construct() {
$this->includes();
if ( function_exists( 'BorlabsCookieHelper' ) ) {
add_action( 'init', array( $this, 'borlabs_cookie' ) );
}
add_action( 'wp_ajax_store_search', array( $this, 'store_search' ) );
add_action( 'wp_ajax_nopriv_store_search', array( $this, 'store_search' ) );
add_action( 'wp_enqueue_scripts', array( $this, 'add_frontend_styles' ) );
add_action( 'wp_footer', array( $this, 'add_frontend_scripts' ) );
add_filter( 'the_content', array( $this, 'cpt_template' ) );
add_shortcode( 'wpsl', array( $this, 'show_store_locator' ) );
add_shortcode( 'wpsl_address', array( $this, 'show_store_address' ) );
add_shortcode( 'wpsl_hours', array( $this, 'show_opening_hours' ) );
add_shortcode( 'wpsl_map', array( $this, 'show_store_map' ) );
}
/**
* Include the required front-end files.
*
* @since 2.0.0
* @return void
*/
public function includes() {
require_once( WPSL_PLUGIN_DIR . 'frontend/underscore-functions.php' );
}
/**
* Include the required file for the borlabs cookie plugin to work.
*
* @since 2.2.22
* @return void
*/
public function borlabs_cookie() {
require_once( WPSL_PLUGIN_DIR . 'inc/class-borlabs-cookie.php' );
}
/**
* Handle the Ajax search on the frontend.
*
* @since 1.0.0
* @return json A list of store locations that are located within the selected search radius
*/
public function store_search() {
global $wpsl_settings;
/*
* Check if auto loading the locations on page load is enabled.
*
* If so then we save the store data in a transient to prevent a long loading time
* in case a large amount of locations need to be displayed.
*
* The SQL query that selects nearby locations doesn't take that long,
* but collecting all the store meta data in get_store_meta_data() for hunderds,
* or thousands of stores can make it really slow.
*/
if ( $wpsl_settings['autoload'] && isset( $_GET['autoload'] ) && $_GET['autoload'] && !$wpsl_settings['debug'] && !isset( $_GET['skip_cache'] ) ) {
$transient_name = $this->create_transient_name();
if ( false === ( $store_data = get_transient( 'wpsl_autoload_' . $transient_name ) ) ) {
$store_data = $this->find_nearby_locations();
if ( $store_data ) {
set_transient( 'wpsl_autoload_' . $transient_name, $store_data, 0 );
}
}
} else {
$store_data = $this->find_nearby_locations();
}
do_action( 'wpsl_store_search' );
wp_send_json( $store_data );
exit();
}
/**
* Create the name used in the wpsl autoload transient.
*
* @since 2.1.1
* @return string $transient_name The transient name.
*/
public function create_transient_name() {
global $wpsl, $wpsl_settings;
$name_section = array();
// Include the set autoload limit.
if ( $wpsl_settings['autoload'] && $wpsl_settings['autoload_limit'] ) {
$name_section[] = absint( $wpsl_settings['autoload_limit'] );
}
/*
* Check if we need to include the cat id(s) in the transient name.
*
* This can only happen if the user used the
* 'category' attr on the wpsl shortcode.
*/
if ( isset( $_GET['filter'] ) && $_GET['filter'] ) {
$name_section[] = absint( str_replace( ',', '', $_GET['filter'] ) );
}
// Include the lat value from the start location.
if ( isset( $_GET['lat'] ) && $_GET['lat'] ) {
$name_section[] = absint( str_replace( '.', '', $_GET['lat'] ) );
}
/*
* If a multilingual plugin ( WPML or qTranslate X ) is active then we have
* to make sure each language has his own unique transient. We do this by
* including the lang code in the transient name.
*
* Otherwise if the language is for example set to German on page load,
* and the user switches to Spanish, then he would get the incorrect
* permalink structure ( /de/.. instead or /es/.. ) and translated
* store details.
*/
$lang_code = $wpsl->i18n->check_multilingual_code();
if ( $lang_code ) {
$name_section[] = $lang_code;
}
$transient_name = implode( '_', $name_section );
/*
* If the distance unit filter ( wpsl_distance_unit ) is used to change the km / mi unit based on
* the location of the IP, then we include the km / mi in the transient name. This is done to
* prevent users from seeing the wrong distances from the cached data.
*
* This way one data set can include the distance in km, and the other one the distance in miles.
*/
if ( has_filter( 'wpsl_distance_unit' ) ) {
$transient_name = $transient_name . '_' . wpsl_get_distance_unit();
}
return $transient_name;
}
/**
* Find store locations that are located within the selected search radius.
*
* This happens by calculating the distance between the
* latlng of the searched location, and the latlng from
* the stores in the db.
*
* @since 2.0.0
* @param array $args The arguments to use in the SQL query, only used by add-ons
* @return void|array $store_data The list of stores that fall within the selected range.
*/
public function find_nearby_locations( $args = array() ) {
global $wpdb, $wpsl, $wpsl_settings;
$store_data = array();
/*
* Set the correct earth radius in either km or miles.
* We need this to calculate the distance between two coordinates.
*/
$placeholder_values[] = ( wpsl_get_distance_unit() == 'km' ) ? 6371 : 3959;
// The placeholder values for the prepared statement in the SQL query.
if ( empty( $args ) ) {
$args = $_GET;
}
array_push( $placeholder_values, $args['lat'], $args['lng'], $args['lat'] );
// Check if we need to filter the results by category.
if ( isset( $args['filter'] ) && $args['filter'] ) {
$filter_ids = array_map( 'absint', explode( ',', $args['filter'] ) );
$cat_filter = "INNER JOIN $wpdb->term_relationships AS term_rel ON posts.ID = term_rel.object_id
INNER JOIN $wpdb->term_taxonomy AS term_tax ON term_rel.term_taxonomy_id = term_tax.term_taxonomy_id
AND term_tax.taxonomy = 'wpsl_store_category'
AND term_tax.term_id IN (" . implode( ',', $filter_ids ) . ")";
} else {
$cat_filter = '';
}
/*
* If WPML is active we include 'GROUP BY lat' in the sql query
* to prevent duplicate locations from showing up in the results.
*
* This is a problem when a store location for example
* exists in 4 different languages. They would all fall within
* the selected radius, but we only need one store ID for the 'icl_object_id'
* function to get the correct store ID for the current language.
*/
if ( $wpsl->i18n->wpml_exists() ) {
$group_by = 'GROUP BY lat';
} else {
$group_by = 'GROUP BY posts.ID';
}
/*
* If autoload is enabled we need to check if there is a limit to the
* amount of locations we need to show.
*
* Otherwise include the radius and max results limit in the sql query.
*/
if ( isset( $args['autoload'] ) && $args['autoload'] ) {
$limit = '';
if ( $wpsl_settings['autoload_limit'] ) {
$limit = 'LIMIT %d';
$placeholder_values[] = $wpsl_settings['autoload_limit'];
}
$sql_sort = 'ORDER BY distance '. $limit;
} else {
array_push( $placeholder_values, $this->check_store_filter( $args, 'search_radius' ), $this->check_store_filter( $args, 'max_results' ) );
$sql_sort = 'HAVING distance < %d ORDER BY distance LIMIT 0, %d';
}
$placeholder_values = apply_filters( 'wpsl_sql_placeholder_values', $placeholder_values );
/*
* The sql that will check which store locations fall within
* the selected radius based on the lat and lng values.
*/
$sql = apply_filters( 'wpsl_sql',
"SELECT post_lat.meta_value AS lat,
post_lng.meta_value AS lng,
posts.ID,
( %d * acos( cos( radians( %s ) ) * cos( radians( post_lat.meta_value ) ) * cos( radians( post_lng.meta_value ) - radians( %s ) ) + sin( radians( %s ) ) * sin( radians( post_lat.meta_value ) ) ) )
AS distance
FROM $wpdb->posts AS posts
INNER JOIN $wpdb->postmeta AS post_lat ON post_lat.post_id = posts.ID AND post_lat.meta_key = 'wpsl_lat'
INNER JOIN $wpdb->postmeta AS post_lng ON post_lng.post_id = posts.ID AND post_lng.meta_key = 'wpsl_lng'
$cat_filter
WHERE posts.post_type = 'wpsl_stores'
AND posts.post_status = 'publish' $group_by $sql_sort"
);
$stores = $wpdb->get_results( $wpdb->prepare( $sql, $placeholder_values ) );
if ( $stores ) {
$store_data = apply_filters( 'wpsl_store_data', $this->get_store_meta_data( $stores ) );
} else {
$store_data = apply_filters( 'wpsl_no_results_sql', '' );
}
return $store_data;
}
/**
* Get the post meta data for the selected stores.
*
* @since 2.0.0
* @param object $stores
* @return array $all_stores The stores that fall within the selected range with the post meta data.
*/
public function get_store_meta_data( $stores ) {
global $wpsl_settings, $wpsl;
$all_stores = array();
// Get the list of store fields that we need to filter out of the post meta data.
$meta_field_map = $this->frontend_meta_fields();
foreach ( $stores as $store_key => $store ) {
// If WPML is active try to get the id of the translated page.
if ( $wpsl->i18n->wpml_exists() ) {
$store->ID = $wpsl->i18n->maybe_get_wpml_id( $store->ID );
if ( !$store->ID ) {
continue;
}
}
// Get the post meta data for each store that was within the range of the search radius.
$custom_fields = get_post_custom( $store->ID );
foreach ( $meta_field_map as $meta_key => $meta_value ) {
if ( isset( $custom_fields[$meta_key][0] ) ) {
if ( ( isset( $meta_value['type'] ) ) && ( !empty( $meta_value['type'] ) ) ) {
$meta_type = $meta_value['type'];
} else {
$meta_type = '';
}
// If we need to hide the opening hours, and the current meta type is set to hours we skip it.
if ( $wpsl_settings['hide_hours'] && $meta_type == 'hours' ) {
continue;
}
// Make sure the data is safe to use on the frontend and in the format we expect it to be.
switch ( $meta_type ) {
case 'numeric':
$meta_data = ( is_numeric( $custom_fields[$meta_key][0] ) ) ? $custom_fields[$meta_key][0] : 0 ;
break;
case 'email':
$meta_data = sanitize_email( $custom_fields[$meta_key][0] );
break;
case 'url':
$meta_data = esc_url( $custom_fields[$meta_key][0] );
break;
case 'hours':
$meta_data = $this->get_opening_hours( $custom_fields[$meta_key][0], apply_filters( 'wpsl_hide_closed_hours', false ) );
break;
case 'wp_editor':
case 'textarea':
$meta_data = wp_kses_post( wpautop( $custom_fields[$meta_key][0] ) );
break;
case 'text':
default:
$meta_data = sanitize_text_field( stripslashes( $custom_fields[$meta_key][0] ) );
break;
}
$store_meta[$meta_value['name']] = $meta_data;
} else {
$store_meta[$meta_value['name']] = '';
}
/*
* Include the post content if the "More info" option is enabled on the settings page,
* or if $include_post_content is set to true through the 'wpsl_include_post_content' filter.
*/
if ( ( $wpsl_settings['more_info'] && $wpsl_settings['more_info_location'] == 'store listings' ) || apply_filters( 'wpsl_include_post_content', false ) ) {
$page_object = get_post( $store->ID );
// Check if we need to strip the shortcode from the post content.
if ( apply_filters( 'wpsl_strip_content_shortcode', true ) ) {
$post_content = strip_shortcodes( $page_object->post_content );
} else {
$post_content = $page_object->post_content;
}
$store_meta['description'] = apply_filters( 'the_content', $post_content );
}
$store_meta['store'] = get_the_title( $store->ID );
$store_meta['thumb'] = $this->get_store_thumb( $store->ID, $store_meta['store'] );
$store_meta['id'] = $store->ID;
if ( !$wpsl_settings['hide_distance'] ) {
$store_meta['distance'] = round( $store->distance, 1 );
}
if ( $wpsl_settings['permalinks'] ) {
$store_meta['permalink'] = get_permalink( $store->ID );
}
}
$all_stores[] = apply_filters( 'wpsl_store_meta', $store_meta, $store->ID );
}
return $all_stores;
}
/**
* The store meta fields that are included in the json output.
*
* The wpsl_ is the name in db, the name value is used as the key in the json output.
*
* The type itself is used to determine how the value should be sanitized.
* Text will go through sanitize_text_field, email through sanitize_email and so on.
*
* If no type is set it will default to sanitize_text_field.
*
* @since 2.0.0
* @return array $store_fields The names of the meta fields used by the store
*/
public function frontend_meta_fields() {
$store_fields = array(
'wpsl_address' => array(
'name' => 'address'
),
'wpsl_address2' => array(
'name' => 'address2'
),
'wpsl_city' => array(
'name' => 'city'
),
'wpsl_state' => array(
'name' => 'state'
),
'wpsl_zip' => array(
'name' => 'zip'
),
'wpsl_country' => array(
'name' => 'country'
),
'wpsl_lat' => array(
'name' => 'lat',
'type' => 'numeric'
),
'wpsl_lng' => array(
'name' => 'lng',
'type' => 'numeric'
),
'wpsl_phone' => array(
'name' => 'phone'
),
'wpsl_fax' => array(
'name' => 'fax'
),
'wpsl_email' => array(
'name' => 'email',
'type' => 'email'
),
'wpsl_hours' => array(
'name' => 'hours',
'type' => 'hours'
),
'wpsl_url' => array(
'name' => 'url',
'type' => 'url'
)
);
return apply_filters( 'wpsl_frontend_meta_fields', $store_fields );
}
/**
* Get the store thumbnail.
*
* @since 2.0.0
* @param string $post_id The post id of the store
* @param string $store_name The name of the store
* @return void|string $thumb The html img tag
*/
public function get_store_thumb( $post_id, $store_name ) {
$attr = array(
'class' => 'wpsl-store-thumb',
'alt' => $store_name
);
$thumb = get_the_post_thumbnail( $post_id, $this->get_store_thumb_size(), apply_filters( 'wpsl_thumb_attr', $attr ) );
return $thumb;
}
/**
* Get the store thumbnail size.
*
* @since 2.0.0
* @return array $size The thumb format
*/
public function get_store_thumb_size() {
$size = apply_filters( 'wpsl_thumb_size', array( 45, 45 ) );
return $size;
}
/**
* Get the opening hours in the correct format.
*
* Either convert the hour values that are set through
* a dropdown to a table, or wrap the textarea input in a <p>.
*
* Note: The opening hours can only be set in the textarea format by users who upgraded from 1.x.
*
* @since 2.0.0
* @param array|string $hours The opening hours
* @param boolean $hide_closed Hide the days were the location is closed
* @return string $hours The formated opening hours
*/
public function get_opening_hours( $hours, $hide_closed ) {
$hours = maybe_unserialize( $hours );
/*
* If the hours are set through the dropdown then we create a table for the opening hours.
* Otherwise we output the data entered in the textarea.
*/
if ( is_array( $hours ) ) {
$hours = $this->create_opening_hours_tabel( $hours, $hide_closed );
} else {
$hours = wp_kses_post( wpautop( $hours ) );
}
return $hours;
}
/**
* Create a table for the opening hours.
*
* @since 2.0.0
* @todo add schema.org support.
* @param array $hours The opening hours
* @param boolean $hide_closed Hide the days where the location is closed
* @return string $hour_table The opening hours sorted in a table
*/
public function create_opening_hours_tabel( $hours, $hide_closed ) {
$opening_days = wpsl_get_weekdays();
// Make sure that we have actual opening hours, and not every day is empty.
if ( $this->not_always_closed( $hours ) ) {
$hour_table = '<table role="presentation" class="wpsl-opening-hours">';
foreach ( $opening_days as $index => $day ) {
$i = 0;
$hour_count = count( $hours[$index] );
// If we need to hide days that are set to closed then skip them.
if ( $hide_closed && !$hour_count ) {
continue;
}
$hour_table .= '<tr>';
$hour_table .= '<td>' . esc_html( $day ) . '</td>';
// If we have opening hours we show them, otherwise just show 'Closed'.
if ( $hour_count > 0 ) {
$hour_table .= '<td>';
while ( $i < $hour_count ) {
$hour = explode( ',', $hours[$index][$i] );
$hour_table .= '<time>' . esc_html( $hour[0] ) . ' - ' . esc_html( $hour[1] ) . '</time>';
$i++;
}
$hour_table .= '</td>';
} else {
$hour_table .= '<td>' . __( 'Closed', 'wpsl' ) . '</td>';
}
$hour_table .= '</tr>';
}
$hour_table .= '</table>';
return $hour_table;
}
}
/**
* Create the wpsl post type output.
*
* If you want to create a custom template you need to
* create a single-wpsl_stores.php file in your theme folder.
* You can see an example here https://wpstorelocator.co/document/create-custom-store-page-template/
*
* @since 2.0.0
* @param string $content
* @return string $content
*/
public function cpt_template( $content ) {
global $wpsl_settings, $post;
$skip_cpt_template = apply_filters( 'wpsl_skip_cpt_template', false );
if ( isset( $post->post_type ) && $post->post_type == 'wpsl_stores' && is_single() && in_the_loop() && !$skip_cpt_template ) {
array_push( $this->load_scripts, 'wpsl_base' );
$content .= '[wpsl_map]';
$content .= '[wpsl_address]';
if ( !$wpsl_settings['hide_hours'] ) {
$content .= '[wpsl_hours]';
}
}
return $content;
}
/**
* Handle the [wpsl] shortcode attributes.
*
* @since 2.1.1
* @param array $atts Shortcode attributes
*/
public function check_sl_shortcode_atts( $atts ) {
/*
* Use a custom start location?
*
* If the provided location fails to geocode,
* then the start location from the settings page is used.
*/
if ( isset( $atts['start_location'] ) && $atts['start_location'] ) {
$start_latlng = wpsl_check_latlng_transient( $atts['start_location'] );
if ( isset( $start_latlng ) && $start_latlng ) {
$this->sl_shortcode_atts['js']['startLatlng'] = $start_latlng;
}
}
if ( isset( $atts['auto_locate'] ) && $atts['auto_locate'] ) {
$this->sl_shortcode_atts['js']['autoLocate'] = ( $atts['auto_locate'] == 'true' ) ? 1 : 0;
}
// Change the category slugs into category ids.
if ( isset( $atts['category'] ) && $atts['category'] ) {
$term_ids = wpsl_get_term_ids( $atts['category'] );
if ( $term_ids ) {
$this->sl_shortcode_atts['js']['categoryIds'] = implode( ',', $term_ids );
}
}
if ( isset( $atts['category_selection'] ) && $atts['category_selection'] ) {
$this->sl_shortcode_atts['category_selection'] = wpsl_get_term_ids( $atts['category_selection'] );
}
if ( isset( $atts['category_filter_type'] ) && in_array( $atts['category_filter_type'], array( 'dropdown', 'checkboxes' ) ) ) {
$this->sl_shortcode_atts['category_filter_type'] = $atts['category_filter_type'];
}
if ( isset( $atts['checkbox_columns'] ) && is_numeric( $atts['checkbox_columns'] ) ) {
$this->sl_shortcode_atts['checkbox_columns'] = $atts['checkbox_columns'];
}
if ( isset( $atts['map_type'] ) && array_key_exists( $atts['map_type'], wpsl_get_map_types() ) ) {
$this->sl_shortcode_atts['js']['mapType'] = $atts['map_type'];
}
if ( isset( $atts['start_marker'] ) && $atts['start_marker'] ) {
$this->sl_shortcode_atts['js']['startMarker'] = $atts['start_marker'] . '@2x.png';
}
if ( isset( $atts['store_marker'] ) && $atts['store_marker'] ) {
$this->sl_shortcode_atts['js']['storeMarker'] = $atts['store_marker'] . '@2x.png';
}
}
/**
* Handle the [wpsl] shortcode.
*
* @since 1.0.0
* @param array $atts Shortcode attributes
* @return string $output The wpsl template
*/
public function show_store_locator( $atts ) {
global $wpsl, $wpsl_settings;
$atts = shortcode_atts( array(
'template' => $wpsl_settings['template_id'],
'start_location' => '',
'auto_locate' => '',
'category' => '',
'category_selection' => '',
'category_filter_type' => '',
'checkbox_columns' => '3',
'map_type' => '',
'start_marker' => '',
'store_marker' => ''
), $atts );
$this->check_sl_shortcode_atts( $atts );
// Make sure the required scripts are included for the wpsl shortcode.
array_push( $this->load_scripts, 'wpsl_store_locator' );
$template_details = $wpsl->templates->get_template_details( $atts['template'] );
$output = include( $template_details['path'] );
return $output;
}
/**
* Handle the [wpsl_address] shortcode.
*
* @since 2.0.0
* @todo add schema.org support.
* @param array $atts Shortcode attributes
* @return void|string $output The store address
*/
public function show_store_address( $atts ) {
global $post, $wpsl_settings, $wpsl;
$atts = wpsl_bool_check( shortcode_atts( apply_filters( 'wpsl_address_shortcode_defaults', array(
'id' => '',
'name' => true,
'address' => true,
'address2' => true,
'city' => true,
'state' => true,
'zip' => true,
'country' => true,
'phone' => true,
'fax' => true,
'email' => true,
'url' => true,
'directions' => false,
'clickable_contact_details' => (bool) $wpsl_settings['clickable_contact_details']
) ), $atts ) );
if ( get_post_type() == 'wpsl_stores' ) {
if ( empty( $atts['id'] ) ) {
if ( isset( $post->ID ) ) {
$atts['id'] = $post->ID;
} else {
return;
}
}
} else if ( empty( $atts['id'] ) ) {
return __( 'If you use the [wpsl_address] shortcode outside a store page you need to set the ID attribute.', 'wpsl' );
}
$content = '<div class="wpsl-locations-details">';
if ( $atts['name'] && $name = get_the_title( $atts['id'] ) ) {
$content .= '<span><strong>' . esc_html( $name ) . '</strong></span>';
}
$content .= '<div class="wpsl-location-address">';
if ( $atts['address'] && $address = get_post_meta( $atts['id'], 'wpsl_address', true ) ) {
$content .= '<span>' . esc_html( $address ) . '</span><br/>';
}
if ( $atts['address2'] && $address2 = get_post_meta( $atts['id'], 'wpsl_address2', true ) ) {
$content .= '<span>' . esc_html( $address2 ) . '</span><br/>';
}
$address_format = explode( '_', $wpsl_settings['address_format'] );
$count = count( $address_format );
$i = 1;
// Loop over the address parts to make sure they are shown in the right order.
foreach ( $address_format as $address_part ) {
// Make sure the shortcode attribute is set to true for the $address_part, and it's not the 'comma' part.
if ( $address_part != 'comma' && $atts[$address_part] ) {
$post_meta = get_post_meta( $atts['id'], 'wpsl_' . $address_part, true );
if ( $post_meta ) {
/*
* Check if the next part of the address is set to 'comma'.
* If so add the, after the current address part, otherwise just show a space
*/
if ( isset( $address_format[$i] ) && ( $address_format[$i] == 'comma' ) ) {
$punctuation = ', ';
} else {
$punctuation = ' ';
}
// If we have reached the last item add a <br /> behind it.
$br = ( $count == $i ) ? '<br />' : '';
$content .= '<span>' . esc_html( $post_meta ) . $punctuation . '</span>' . $br;
}
}
$i++;
}
if ( $atts['country'] && $country = get_post_meta( $atts['id'], 'wpsl_country', true ) ) {
$content .= '<span>' . esc_html( $country ) . '</span>';
}
$content .= '</div>';
// If either the phone, fax, email or url is set to true, then add the wrap div for the contact details.
if ( $atts['phone'] || $atts['fax'] || $atts['email'] || $atts['url'] ) {
$phone = get_post_meta( $atts['id'], 'wpsl_phone', true );
$fax = get_post_meta( $atts['id'], 'wpsl_fax', true );
$email = get_post_meta( $atts['id'], 'wpsl_email', true );
if ( $atts['clickable_contact_details'] ) {
$contact_details = array(
'phone' => '<a href="tel:' . esc_attr( $phone ) . '">' . esc_html( $phone ) . '</a>',
'fax' => '<a href="tel:' . esc_attr( $fax ) . '">' . esc_html( $fax ) . '</a>',
'email' => '<a href="mailto:' . sanitize_email( $email ) . '">' . sanitize_email( $email ) . '</a>'
);
} else {
$contact_details = array(
'phone' => esc_html( $phone ),
'fax' => esc_html( $fax ),
'email' => sanitize_email( $email )
);
}
$content .= '<div class="wpsl-contact-details">';
if ( $atts['phone'] && $phone ) {
$content .= esc_html( $wpsl->i18n->get_translation( 'phone_label', __( 'Phone', 'wpsl' ) ) ) . ': <span>' . $contact_details['phone'] . '</span><br/>';
}
if ( $atts['fax'] && $fax ) {
$content .= esc_html( $wpsl->i18n->get_translation( 'fax_label', __( 'Fax', 'wpsl' ) ) ) . ': <span>' . $contact_details['fax'] . '</span><br/>';
}
if ( $atts['email'] && $email ) {
$content .= esc_html( $wpsl->i18n->get_translation( 'email_label', __( 'Email', 'wpsl' ) ) ) . ': <span>' . $contact_details['email'] . '</span><br/>';
}
if ( $atts['url'] && $store_url = get_post_meta( $atts['id'], 'wpsl_url', true ) ) {
$new_window = ( $wpsl_settings['new_window'] ) ? 'target="_blank"' : '' ;
$content .= esc_html( $wpsl->i18n->get_translation( 'url_label', __( 'Url', 'wpsl' ) ) ) . ': <a ' . $new_window . ' href="' . esc_url( $store_url ) . '">' . esc_url( $store_url ) . '</a><br/>';
}
$content .= '</div>';
}
if ( $atts['directions'] && $address ) {
if ( $wpsl_settings['new_window'] ) {
$new_window = ' target="_blank"';
} else {
$new_window = '';
}
$content .= '<div class="wpsl-location-directions">';
$city = get_post_meta( $atts['id'], 'wpsl_city', true );
$country = get_post_meta( $atts['id'], 'wpsl_country', true );
$destination = $address . ',' . $city . ',' . $country;
$direction_url = "https://maps.google.com/maps?saddr=&daddr=" . urlencode( $destination ) . "&travelmode=" . strtolower( $this->get_directions_travel_mode() );
$content .= '<p><a ' . $new_window . ' href="' . esc_url( $direction_url ) . '">' . __( 'Directions', 'wpsl' ) . '</a></p>';
$content .= '</div>';
}
$content .= '</div>';
return $content;
}
/**
* Handle the [wpsl_hours] shortcode.
*
* @since 2.0.0
* @param array $atts Shortcode attributes
* @return void|string $output The opening hours
*/
public function show_opening_hours( $atts ) {
global $wpsl_settings, $post;
// If the hours are set to hidden on the settings page, then respect that and don't continue.
if ( $wpsl_settings['hide_hours'] ) {
return;
}
$hide_closed = apply_filters( 'wpsl_hide_closed_hours', false );
$atts = wpsl_bool_check( shortcode_atts( apply_filters( 'wpsl_hour_shortcode_defaults', array(
'id' => '',
'hide_closed' => $hide_closed
) ), $atts ) );
if ( get_post_type() == 'wpsl_stores' ) {
if ( empty( $atts['id'] ) ) {
if ( isset( $post->ID ) ) {
$atts['id'] = $post->ID;
} else {
return;
}
}
} else if ( empty( $atts['id'] ) ) {
return __( 'If you use the [wpsl_hours] shortcode outside a store page you need to set the ID attribute.', 'wpsl' );
}
$opening_hours = get_post_meta( $atts['id'], 'wpsl_hours' );
if ( $opening_hours ) {
$output = $this->get_opening_hours( $opening_hours[0], $atts['hide_closed'] );
return $output;
}
}
/**
* Handle the [wpsl_map] shortcode.
*
* @since 2.0.0
* @param array $atts Shortcode attributes
* @return string $output The html for the map
*/
public function show_store_map( $atts ) {
global $wpsl_settings, $post;
$atts = shortcode_atts( apply_filters( 'wpsl_map_shortcode_defaults', array(
'id' => '',
'category' => '',
'width' => '',
'height' => $wpsl_settings['height'],
'zoom' => $wpsl_settings['zoom_level'],
'map_type' => $wpsl_settings['map_type'],
'map_type_control' => $wpsl_settings['type_control'],
'map_style' => '',
'street_view' => $wpsl_settings['streetview'],
'scrollwheel' => $wpsl_settings['scrollwheel'],
'control_position' => $wpsl_settings['control_position']
) ), $atts );
array_push( $this->load_scripts, 'wpsl_base' );
if ( get_post_type() == 'wpsl_stores' ) {
if ( empty( $atts['id'] ) ) {
if ( isset( $post->ID ) ) {
$atts['id'] = $post->ID;
} else {
return;
}
}
} else if ( empty( $atts['id'] ) && empty( $atts['category'] ) ) {
return __( 'If you use the [wpsl_map] shortcode outside a store page, then you need to set the ID or category attribute.', 'wpsl' );
}
if ( $atts['category'] ) {
$store_ids = get_posts( array(
'numberposts' => -1,
'post_type' => 'wpsl_stores',
'post_status' => 'publish',
'tax_query' => array(
array(
'taxonomy' => 'wpsl_store_category',
'field' => 'slug',
'terms' => explode( ',', sanitize_text_field( $atts['category'] ) )
),
),
'fields' => 'ids'
) );
} else {
$store_ids = array_map( 'absint', explode( ',', $atts['id'] ) );
$id_count = count( $store_ids );
}
/*
* The location url is included if:
*
* - Multiple ids are set.
* - The category attr is set.
* - The shortcode is used on a post type other then 'wpsl_stores'. No point in showing a location
* url to the user that links back to the page they are already on.
*/
if ( $atts['category'] || isset( $id_count ) && $id_count > 1 || get_post_type() != 'wpsl_stores' && !empty( $atts['id'] ) ) {
$incl_url = true;
} else {
$incl_url = false;
}
$store_meta = array();
$i = 0;
foreach ( $store_ids as $store_id ) {
$lat = get_post_meta( $store_id, 'wpsl_lat', true );
$lng = get_post_meta( $store_id, 'wpsl_lng', true );
// Make sure the latlng is numeric before collecting the other meta data.
if ( is_numeric( $lat ) && is_numeric( $lng ) ) {
$store_meta[$i] = apply_filters( 'wpsl_cpt_info_window_meta_fields', array(
'store' => get_the_title( $store_id ),
'address' => get_post_meta( $store_id, 'wpsl_address', true ),
'address2' => get_post_meta( $store_id, 'wpsl_address2', true ),
'city' => get_post_meta( $store_id, 'wpsl_city', true ),
'state' => get_post_meta( $store_id, 'wpsl_state', true ),
'zip' => get_post_meta( $store_id, 'wpsl_zip', true ),
'country' => get_post_meta( $store_id, 'wpsl_country', true )
), $store_id );
// Grab the permalink / url if necessary.
if ( $incl_url ) {
if ( $wpsl_settings['permalinks'] ) {
$store_meta[$i]['permalink'] = get_permalink( $store_id );
} else {
$store_meta[$i]['url'] = get_post_meta( $store_id, 'wpsl_url', true );
}
}
$store_meta[$i]['lat'] = $lat;
$store_meta[$i]['lng'] = $lng;
$store_meta[$i]['id'] = $store_id;
$i++;
}
}
$output = '<div id="wpsl-base-gmap_' . self::$map_count . '" class="wpsl-gmap-canvas"></div>' . "\r\n";
// Make sure the shortcode attributes are valid.
$map_styles = $this->check_map_shortcode_atts( $atts );
if ( $map_styles ) {
if ( isset( $map_styles['css'] ) && !empty( $map_styles['css'] ) ) {
$output .= '<style>' . $map_styles['css'] . '</style>' . "\r\n";
unset( $map_styles['css'] );
}
if ( $map_styles ) {
$store_data['shortCode'] = $map_styles;
}
}
$store_data['locations'] = $store_meta;
$this->store_map_data[self::$map_count] = $store_data;
self::$map_count++;
return $output;
}
/**
* Make sure the map style shortcode attributes are valid.
*
* The values are send to wp_localize_script in add_frontend_scripts.
*
* @since 2.0.0
* @param array $atts The map style shortcode attributes
* @return array $map_atts Validated map style shortcode attributes
*/
public function check_map_shortcode_atts( $atts ) {
$map_atts = array();
if ( isset( $atts['width'] ) && is_numeric( $atts['width'] ) ) {
$width = 'width:' . $atts['width'] . 'px;';
} else {
$width = '';
}
if ( isset( $atts['height'] ) && is_numeric( $atts['height'] ) ) {
$height = 'height:' . $atts['height'] . 'px;';
} else {
$height = '';
}
if ( $width || $height ) {
$map_atts['css'] = '#wpsl-base-gmap_' . self::$map_count . ' {' . $width . $height . '}';
}
if ( isset( $atts['zoom'] ) && !empty( $atts['zoom'] ) ) {
$map_atts['zoomLevel'] = wpsl_valid_zoom_level( $atts['zoom'] );
}
if ( isset( $atts['map_type'] ) && !empty( $atts['map_type'] ) ) {
$map_atts['mapType'] = wpsl_valid_map_type( $atts['map_type'] );
}
if ( isset( $atts['map_type_control'] ) ) {
$map_atts['mapTypeControl'] = $this->shortcode_atts_boolean( $atts['map_type_control'] );
}
if ( isset( $atts['map_style'] ) && $atts['map_style'] == 'default' ) {
$map_atts['mapStyle'] = '';
}
if ( isset( $atts['street_view'] ) ) {
$map_atts['streetView'] = $this->shortcode_atts_boolean( $atts['street_view'] );
}
if ( isset( $atts['scrollwheel'] ) ) {
$map_atts['scrollWheel'] = $this->shortcode_atts_boolean( $atts['scrollwheel'] );
}
if ( isset( $atts['control_position'] ) && !empty( $atts['control_position'] ) && ( $atts['control_position'] == 'left' || $atts['control_position'] == 'right' ) ) {
$map_atts['controlPosition'] = $atts['control_position'];
}
return $map_atts;
}
/**
* Set the shortcode attribute to either 1 or 0.
*
* @since 2.0.0
* @param string $att The shortcode attribute val
* @return int $att_val Either 1 or 0
*/
public function shortcode_atts_boolean( $att ) {
if ( $att === 'true' || absint( $att ) ) {
$att_val = 1;
} else {
$att_val = 0;
}
return $att_val;
}
/**
* Make sure the filter contains a valid value, otherwise use the default value.
*
* @since 2.0.0
* @param array $args The values used in the SQL query to find nearby locations
* @param string $filter The name of the filter
* @return string $filter_value The filter value
*/
public function check_store_filter( $args, $filter ) {
if ( isset( $args[$filter] ) && absint( $args[$filter] ) && $this->check_allowed_filter_value( $args, $filter ) ) {
$filter_value = $args[$filter];
} else {
$filter_value = $this->get_default_filter_value( $filter );
}
return $filter_value;
}
/**
* Make sure the used filter value isn't bigger
* then the value that's set on the settings page.
*
* @since 2.2.9
* @param array $args The values used in the SQL query to find nearby locations
* @param string $filter The name of the filter
* @return bool $allowed True if the value is equal or smaller then the value from the settings page
*/
public function check_allowed_filter_value( $args, $filter ) {
global $wpsl_settings;
$allowed = false;
$max_filter_val = max( explode(',', str_replace( array( '[',']' ), '', $wpsl_settings[$filter] ) ) );
if ( (int) $args[$filter] <= (int) $max_filter_val ) {
$allowed = true;
}
return $allowed;
}
/**
* Get the default selected value for a dropdown.
*
* @since 1.0.0
* @param string $type The request list type
* @return string $response The default list value
*/
public function get_default_filter_value( $type ) {
$settings = get_option( 'wpsl_settings' );
$list_values = explode( ',', $settings[$type] );
foreach ( $list_values as $k => $list_value ) {
// The default radius has a [] wrapped around it, so we check for that and filter out the [].
if ( strpos( $list_value, '[' ) !== false ) {
$response = filter_var( $list_value, FILTER_SANITIZE_NUMBER_INT );
break;
}
}
return $response;
}
/**
* Check if we have a opening day that has an value, if not they are all set to closed.
*
* @since 2.0.0
* @param array $opening_hours The opening hours
* @return boolean True if a day is found that isn't empty
*/
public function not_always_closed( $opening_hours ) {
foreach ( $opening_hours as $hours => $hour ) {
if ( !empty( $hour ) ) {
return true;
}
}
}
/**
* Create the css rules based on the height / max-width that is set on the settings page.
*
* @since 1.0.0
* @return string $css The custom css rules
*/
public function get_custom_css() {
global $wpsl_settings;
$thumb_size = $this->get_store_thumb_size();
$css = '<style>' . "\r\n";
if ( isset( $thumb_size[0] ) && is_numeric( $thumb_size[0] ) && isset( $thumb_size[1] ) && is_numeric( $thumb_size[1] ) ) {
$css .= "\t" . "#wpsl-stores .wpsl-store-thumb {height:" . esc_attr( $thumb_size[0] ) . "px !important; width:" . esc_attr( $thumb_size[1] ) . "px !important;}" . "\r\n";
}
if ( $wpsl_settings['template_id'] == 'below_map' && $wpsl_settings['listing_below_no_scroll'] ) {
$css .= "\t" . "#wpsl-gmap {height:" . esc_attr( $wpsl_settings['height'] ) . "px !important;}" . "\r\n";
$css .= "\t" . "#wpsl-stores, #wpsl-direction-details {height:auto !important;}";
} else {
$css .= "\t" . "#wpsl-stores, #wpsl-direction-details, #wpsl-gmap {height:" . esc_attr( $wpsl_settings['height'] ) . "px !important;}" . "\r\n";
}
/*
* If the category dropdowns are enabled then we make it
* the same width as the search input field.
*/
if ( $wpsl_settings['category_filter'] && $wpsl_settings['category_filter_type'] == 'dropdown' || isset( $this->sl_shortcode_atts['category_filter_type'] ) && $this->sl_shortcode_atts['category_filter_type'] == 'dropdown' ) {
$cat_elem = ',#wpsl-category .wpsl-dropdown';
} else {
$cat_elem = '';
}
$css .= "\t" . "#wpsl-gmap .wpsl-info-window {max-width:" . esc_attr( $wpsl_settings['infowindow_width'] ) . "px !important;}" . "\r\n";
$css .= "\t" . ".wpsl-input label, #wpsl-radius label, #wpsl-category label {width:" . esc_attr( $wpsl_settings['label_width'] ) . "px;}" . "\r\n";
$css .= "\t" . "#wpsl-search-input " . $cat_elem . " {width:" . esc_attr( $wpsl_settings['search_width'] ) . "px;}" . "\r\n";
$css .= '</style>' . "\r\n";
return $css;
}
/**
* Collect the CSS classes that are placed on the outer store locator div.
*
* @since 2.0.0
* @return string $classes The custom CSS rules
*/
public function get_css_classes() {
global $wpsl_settings;
$classes = array();
if ( $wpsl_settings['category_filter'] && $wpsl_settings['results_dropdown'] && !$wpsl_settings['radius_dropdown'] ) {
$classes[] = 'wpsl-cat-results-filter';
} else if ( $wpsl_settings['category_filter'] && ( $wpsl_settings['results_dropdown'] || $wpsl_settings['radius_dropdown'] ) ) {
$classes[] = 'wpsl-filter';
}
// checkboxes class toevoegen?
if ( !$wpsl_settings['category_filter'] && !$wpsl_settings['results_dropdown'] && !$wpsl_settings['radius_dropdown'] ) {
$classes[] = 'wpsl-no-filters';
}
if ( $wpsl_settings['category_filter'] && $wpsl_settings['category_filter_type'] == 'checkboxes' ) {
$classes[] = 'wpsl-checkboxes-enabled';
}
if ( $wpsl_settings['results_dropdown'] && !$wpsl_settings['category_filter'] && !$wpsl_settings['radius_dropdown'] ) {
$classes[] = 'wpsl-results-only';
}
// Adjust the styling of the store locator for the default WP 5.0 theme.
if ( get_option( 'template' ) === 'twentynineteen' ) {
$classes[] = 'wpsl-twentynineteen';
}
$classes = apply_filters( 'wpsl_template_css_classes', $classes );
if ( !empty( $classes ) ) {
return join( ' ', $classes );
}
}
/**
* Create a dropdown list holding the search radius or
* max search results options.
*
* @since 1.0.0
* @param string $list_type The name of the list we need to load data for
* @return string $dropdown_list A list with the available options for the dropdown list
*/
public function get_dropdown_list( $list_type ) {
global $wpsl_settings;
$dropdown_list = '';
$settings = explode( ',', $wpsl_settings[$list_type] );
// Only show the distance unit if we are dealing with the search radius.
if ( $list_type == 'search_radius' ) {
$distance_unit = ' '. esc_attr( wpsl_get_distance_unit() );
} else {
$distance_unit = '';
}
foreach ( $settings as $index => $setting_value ) {
// The default radius has a [] wrapped around it, so we check for that and filter out the [].
if ( strpos( $setting_value, '[' ) !== false ) {
$setting_value = filter_var( $setting_value, FILTER_SANITIZE_NUMBER_INT );
$selected = 'selected="selected" ';
} else {
$selected = '';
}
$dropdown_list .= '<option ' . $selected . 'value="'. absint( $setting_value ) .'">'. absint( $setting_value ) . $distance_unit .'</option>';
}
return $dropdown_list;
}
/**
* Check if we need to use a dropdown or checkboxes
* to filter the search results by categories.
*
* @since 2.2.10
* @return bool $use_filter
*/
public function use_category_filter() {
global $wpsl_settings;
$use_filter = false;
// Is a filter type set through the shortcode, or is the filter option enable on the settings page?
if ( isset( $this->sl_shortcode_atts['category_filter_type'] ) || $wpsl_settings['category_filter'] ) {
$use_filter = true;
}
return $use_filter;
}
/**
* Create the category filter.
*
* @todo create another func that accepts a meta key param to generate
* a dropdown with unique values. So for example create_filter( 'restaurant' ) will output a
* filter with all restaurant types. This can be used in a custom theme template.
*
* @since 2.0.0
* @return string|void $category The HTML for the category dropdown, or nothing if no terms exist.
*/
public function create_category_filter() {
global $wpsl, $wpsl_settings;
/*
* If the category attr is set on the wpsl shortcode, then
* there is no need to ouput an extra category dropdown.
*/
if ( isset( $this->sl_shortcode_atts['js']['categoryIds'] ) ) {
return;
}
$terms = get_terms( 'wpsl_store_category' );
if ( count( $terms ) > 0 ) {
// Either use the shortcode atts filter type or the one from the settings page.
if ( isset( $this->sl_shortcode_atts['category_filter_type'] ) ) {
$filter_type = $this->sl_shortcode_atts['category_filter_type'];
} else {
$filter_type = $wpsl_settings['category_filter_type'];
}
// Check if we need to show the filter as checkboxes or a dropdown list
if ( $filter_type == 'checkboxes' ) {
if ( isset( $this->sl_shortcode_atts['checkbox_columns'] ) ) {
$checkbox_columns = absint( $this->sl_shortcode_atts['checkbox_columns'] );
}
if ( isset( $checkbox_columns ) && $checkbox_columns ) {
$column_count = $checkbox_columns;
} else {
$column_count = 3;
}
$category = '<ul id="wpsl-checkbox-filter" class="wpsl-checkbox-' . $column_count . '-columns">';
foreach ( $terms as $term ) {
$category .= '<li>';
$category .= '<label>';
$category .= '<input type="checkbox" value="' . esc_attr( $term->term_id ) . '" ' . $this->set_selected_category( $filter_type, $term->term_id ) . ' />';
$category .= esc_html( $term->name );
$category .= '</label>';
$category .= '</li>';
}
$category .= '</ul>';
} else {
$category = '<div id="wpsl-category">' . "\r\n";
$category .= '<label for="wpsl-category-list">' . esc_html( $wpsl->i18n->get_translation( 'category_label', __( 'Category', 'wpsl' ) ) ) . '</label>' . "\r\n";
$args = apply_filters( 'wpsl_dropdown_category_args', array(
'show_option_none' => $wpsl->i18n->get_translation( 'category_default_label', __( 'Any', 'wpsl' ) ),
'option_none_value' => '0',
'orderby' => 'NAME',
'order' => 'ASC',
'echo' => 0,
'selected' => $this->set_selected_category( $filter_type ),
'hierarchical' => 1,
'name' => 'wpsl-category',
'id' => 'wpsl-category-list',
'class' => 'wpsl-dropdown',
'taxonomy' => 'wpsl_store_category',
'hide_if_empty' => true
)
);
$category .= wp_dropdown_categories( $args );
$category .= '</div>' . "\r\n";
}
return $category;
}
}
/**
* Set the selected category item.
*
* @since 2.1.2
* @param string $filter_type The type of filter being used ( dropdown or checkbox )
* @param int|string $term_id The term id ( checkbox only )
* @return string|void $category The ID of the selected option, or checked='checked' if it's for a checkbox
*/
public function set_selected_category( $filter_type, $term_id = '' ) {
$selected_id = '';
// Check if the ID for the selected cat is either passed through the widget, or shortcode
if ( isset( $_REQUEST['wpsl-widget-categories'] ) ) {
$selected_id = absint( $_REQUEST['wpsl-widget-categories'] );
} else if ( isset( $this->sl_shortcode_atts['category_selection'] ) ) {
/*
* When the term_id is set, then it's a checkbox.
*
* Otherwise select the first value from the provided list since
* multiple selections are not supported in dropdowns.
*/
if ( $term_id ) {
// Check if the passed term id exists in the set shortcode value.
$key = array_search( $term_id, $this->sl_shortcode_atts['category_selection'] );
if ( $key !== false ) {
$selected_id = $this->sl_shortcode_atts['category_selection'][$key];
}
} else {
$selected_id = $this->sl_shortcode_atts['category_selection'][0];
}
}
if ( $selected_id ) {
/*
* Based on the filter type, either return the ID of the selected category,
* or check if the checkbox needs to be set to checked="checked".
*/
if ( $filter_type == 'dropdown' ) {
return $selected_id;
} else {
return checked( $selected_id, $term_id, false );
}
}
}
/**
* Create a filename with @2x in it for the selected marker color.
*
* So when a user selected green.png in the admin panel. The JS on the front-end will end up
* loading green@2x.png to provide support for retina compatible devices.
*
* @since 1.0.0
* @param string $filename The name of the seleted marker
* @return string $filename The filename with @2x added to the end
*/
public function create_retina_filename( $filename ) {
$filename = explode( '.', $filename );
$filename = $filename[0] . '@2x.' . $filename[1];
return $filename;
}
/**
* Get the default values for the max_results and the search_radius dropdown.
*
* @since 1.0.2
* @return array $output The default dropdown values
*/
public function get_dropdown_defaults() {
global $wpsl_settings;
$required_defaults = array(
'max_results',
'search_radius'
);
// Strip out the default values that are wrapped in [].
foreach ( $required_defaults as $required_default ) {
preg_match_all( '/\[([0-9]+?)\]/', $wpsl_settings[$required_default], $match, PREG_PATTERN_ORDER );
$output[$required_default] = ( isset( $match[1][0] ) ) ? $match[1][0] : '25';
}
return $output;
}
/**
* Load the required css styles.
*
* @since 2.0.0
* @return void
*/
public function add_frontend_styles() {
global $wpsl_settings;
/**
* Check if we need to deregister other Google Maps scripts loaded
* by other plugins, or the current theme?
*
* This in some cases can break the store locator map.
*/
if ( $wpsl_settings['deregister_gmaps'] ) {
wpsl_deregister_other_gmaps();
}
$min = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';
wp_enqueue_style( 'wpsl-styles', WPSL_URL . 'css/styles'. $min .'.css', '', WPSL_VERSION_NUM );
}
/**
* Get the HTML for the map controls.
*
* The '' and '' code is for the icon font from fontello.com
*
* @since 2.0.0
* @return string The HTML for the map controls
*/
public function get_map_controls() {
global $wpsl_settings, $is_IE;
$classes = array();
if ( $wpsl_settings['reset_map'] ) {
$reset_button = '<div class="wpsl-icon-reset"><span></span></div>';
} else {
$reset_button = '';
}
/*
* IE messes up the top padding for the icon fonts from fontello >_<.
*
* Luckily it's the same in all IE version ( 8-11 ),
* so adjusting the padding just for IE fixes it.
*/
if ( $is_IE ) {
$classes[] = 'wpsl-ie';
}
// If the street view option is enabled, then we need to adjust the right margin for the map control div.
if ( $wpsl_settings['streetview'] ) {
$classes[] = 'wpsl-street-view-exists';
}
if ( !empty( $classes ) ) {
$class = 'class="' . join( ' ', $classes ) . '"';
} else {
$class = '';
}
$map_controls = '<div id="wpsl-map-controls" ' . $class . '>' . $reset_button . '<div class="wpsl-icon-direction"><span></span></div></div>';
return apply_filters( 'wpsl_map_controls', $map_controls );
}
/**
* The different geolocation errors.
*
* They are shown when the Geolocation API returns an error.
*
* @since 2.0.0
* @return array $geolocation_errors
*/
public function geolocation_errors() {
$geolocation_errors = array(
'denied' => __( 'The application does not have permission to use the Geolocation API.', 'wpsl' ),
'unavailable' => __( 'Location information is unavailable.', 'wpsl' ),
'timeout' => __( 'The geolocation request timed out.', 'wpsl' ),
'generalError' => __( 'An unknown error occurred.', 'wpsl' )
);
return $geolocation_errors;
}
/**
* Get the used marker properties.
*
* @since 2.1.0
* @link https://developers.google.com/maps/documentation/javascript/3.exp/reference#Icon
* @return array $marker_props The marker properties.
*/
public function get_marker_props() {
$marker_props = array(
'scaledSize' => '24,35', // 50% of the normal image to make it work on retina screens.
'origin' => '0,0',
'anchor' => '12,35'
);
/*
* If this is not defined, the url path will default to
* the url path of the WPSL plugin folder + /img/markers/
* in the wpsl-gmap.js.
*/
if ( defined( 'WPSL_MARKER_URI' ) ) {
$marker_props['url'] = WPSL_MARKER_URI;
}
return apply_filters( 'wpsl_marker_props', $marker_props );
}
/**
* Get the used travel direction mode.
*
* @since 2.2.8
* @return string $travel_mode The used travel mode for the travel direcions
*/
public function get_directions_travel_mode() {
$default = 'driving';
$travel_mode = apply_filters( 'wpsl_direction_travel_mode', $default );
$allowed_modes = array( 'driving', 'bicycling', 'transit', 'walking' );
if ( !in_array( $travel_mode, $allowed_modes ) ) {
$travel_mode = $default;
}
return strtoupper( $travel_mode );
}
/**
* Get the map tab anchors.
*
* If the wpsl/wpsl_map shortcode is used in one or more tabs,
* then a JS fix ( the fixGreyTabMap function ) needs to run
* to make sure the map doesn't turn grey.
*
* For the fix to work need to know the used anchor(s).
*
* @since 2.2.10
* @return string|array $map_tab_anchor One or more anchors used to show the map(s)
*/
public function get_map_tab_anchor() {
$map_tab_anchor = apply_filters( 'wpsl_map_tab_anchor', 'wpsl-map-tab' );
return $map_tab_anchor;
}
/**
* Load the required JS scripts.
*
* @since 1.0.0
* @return void
*/
public function add_frontend_scripts() {
global $wpsl_settings, $wpsl, $post;
// Only load the required js files on the store locator page or individual store pages.
if ( empty( $this->load_scripts ) ) {
return;
}
$min = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';
$dropdown_defaults = $this->get_dropdown_defaults();
/**
* Check if we need to deregister other Google Maps scripts loaded
* by other plugins, or the current theme?
*
* This in some cases can break the store locator map.
*/
if ( $wpsl_settings['deregister_gmaps'] ) {
wpsl_deregister_other_gmaps();
}
if ( !function_exists( 'BorlabsCookieHelper' ) ) {
wp_enqueue_script( 'wpsl-gmap', ( 'https://maps.google.com/maps/api/js' . wpsl_get_gmap_api_params( 'browser_key' ) . '' ), '', null, true );
} else {
if ( !$wpsl_settings['delay_loading']
||
(
stripos( $post->post_content, '[borlabs_cookie_blocked_content type="wpstorelocator"' ) === false
&&
stripos( $post->post_content, '[borlabs-cookie id="wpstorelocator" type="content-blocker"' ) === false
)
) {
wp_enqueue_script( 'wpsl-gmap', ( 'https://maps.google.com/maps/api/js' . wpsl_get_gmap_api_params( 'browser_key' ) . '' ), '', null, true );
}
}
$base_settings = array(
'storeMarker' => $this->create_retina_filename( $wpsl_settings['store_marker'] ),
'mapType' => $wpsl_settings['map_type'],
'mapTypeControl' => $wpsl_settings['type_control'],
'zoomLevel' => $wpsl_settings['zoom_level'],
'startLatlng' => $wpsl_settings['start_latlng'],
'autoZoomLevel' => $wpsl_settings['auto_zoom_level'],
'scrollWheel' => $wpsl_settings['scrollwheel'],
'controlPosition' => $wpsl_settings['control_position'],
'url' => WPSL_URL,
'markerIconProps' => $this->get_marker_props(),
'storeUrl' => $wpsl_settings['store_url'],
'maxDropdownHeight' => apply_filters( 'wpsl_max_dropdown_height', 300 ),
'enableStyledDropdowns' => apply_filters( 'wpsl_enable_styled_dropdowns', true ),
'mapTabAnchor' => $this->get_map_tab_anchor(),
'mapTabAnchorReturn' => apply_filters( 'wpsl_map_tab_anchor_return', false ),
'gestureHandling' => apply_filters( 'wpsl_gesture_handling', 'auto' ),
'directionsTravelMode' => $this->get_directions_travel_mode(),
'runFitBounds' => $wpsl_settings['run_fitbounds']
);
$locator_map_settings = array(
'startMarker' => $this->create_retina_filename( $wpsl_settings['start_marker'] ),
'markerClusters' => $wpsl_settings['marker_clusters'],
'streetView' => $wpsl_settings['streetview'],
'autoComplete' => $wpsl_settings['autocomplete'],
'autoLocate' => $wpsl_settings['auto_locate'],
'autoLoad' => $wpsl_settings['autoload'],
'markerEffect' => $wpsl_settings['marker_effect'],
'markerStreetView' => $wpsl_settings['marker_streetview'],
'markerZoomTo' => $wpsl_settings['marker_zoom_to'],
'newWindow' => $wpsl_settings['new_window'],
'resetMap' => $wpsl_settings['reset_map'],
'directionRedirect' => $wpsl_settings['direction_redirect'],
'phoneUrl' => $wpsl_settings['phone_url'],
'clickableDetails' => $wpsl_settings['clickable_contact_details'],
'moreInfoLocation' => $wpsl_settings['more_info_location'],
'mouseFocus' => $wpsl_settings['mouse_focus'],
'templateId' => $wpsl_settings['template_id'],
'maxResults' => $dropdown_defaults['max_results'],
'searchRadius' => $dropdown_defaults['search_radius'],
'distanceUnit' => wpsl_get_distance_unit(),
'geoLocationTimeout' => apply_filters( 'wpsl_geolocation_timeout', 7500 ),
'ajaxurl' => wpsl_get_ajax_url(),
'mapControls' => $this->get_map_controls()
);
/*
* If no results are found then by default it will just show the
* "No results found" text. This filter makes it possible to show
* a custom HTML block instead of the "No results found" text.
*/
$no_results_msg = apply_filters( 'wpsl_no_results', '' );
if ( $no_results_msg ) {
$locator_map_settings['noResults'] = $no_results_msg;
}
/**
* If enabled, include the component filter settings.
* @todo see https://developers.google.com/maps/documentation/javascript/releases#327
* See https://developers.google.com/maps/documentation/javascript/geocoding#ComponentFiltering
*/
if ( $wpsl_settings['api_region'] && $wpsl_settings['api_geocode_component'] ) {
$geocode_components = array();
$geocode_components['country'] = strtoupper( $wpsl_settings['api_region'] );
if ( $wpsl_settings['force_postalcode'] ) {
$geocode_components['postalCode'] = '';
}
$locator_map_settings['geocodeComponents'] = apply_filters( 'wpsl_geocode_components', $geocode_components );
}
/**
* Reduce the requested data fields with each autocomplete API call.
*
* You can see the supported fields here https://developers.google.com/maps/documentation/javascript/reference/places-service#PlaceResult
* and other possible options to target here https://developers.google.com/maps/documentation/javascript/reference/places-widget#AutocompleteOptions
*/
if ( $wpsl_settings['autocomplete'] ) {
$locator_map_settings['autoCompleteOptions'] = apply_filters( 'wpsl_autocomplete_options', array(
'fields' => array( 'geometry.location' ),
'types' => array( '(regions)' )
) );
}
// If the marker clusters are enabled, include the js file and marker settings.
if ( $wpsl_settings['marker_clusters'] ) {
wp_enqueue_script( 'wpsl-cluster', WPSL_URL . 'js/markerclusterer'. $min .'.js', array( 'wpsl-js' ), WPSL_VERSION_NUM, true ); //not minified version is in the /js folder
$base_settings['clusterZoom'] = $wpsl_settings['cluster_zoom'];
$base_settings['clusterSize'] = $wpsl_settings['cluster_size'];
$base_settings['clusterImagePath'] = 'https://cdn.rawgit.com/googlemaps/js-marker-clusterer/gh-pages/images/m';
}
// Check if we need to include the infobox script and settings.
if ( $wpsl_settings['infowindow_style'] == 'infobox' ) {
wp_enqueue_script( 'wpsl-infobox', WPSL_URL . 'js/infobox'. $min .'.js', array( 'wpsl-gmap' ), WPSL_VERSION_NUM, true ); // Not minified version is in the /js folder
$base_settings['infoWindowStyle'] = $wpsl_settings['infowindow_style'];
$base_settings = $this->get_infobox_settings( $base_settings );
}
// Include the map style.
if ( !empty( $wpsl_settings['map_style'] ) ) {
$base_settings['mapStyle'] = strip_tags( stripslashes( json_decode( $wpsl_settings['map_style'] ) ) );
}
wp_enqueue_script( 'wpsl-js', apply_filters( 'wpsl_gmap_js', WPSL_URL . 'js/wpsl-gmap'. $min .'.js' ), array( 'jquery' ), WPSL_VERSION_NUM, true );
wp_enqueue_script( 'underscore' );
// Check if we need to include all the settings and labels or just a part of them.
if ( in_array( 'wpsl_store_locator', $this->load_scripts ) ) {
$settings = wp_parse_args( $base_settings, $locator_map_settings );
$template = 'wpsl_store_locator';
$labels = array(
'preloader' => $wpsl->i18n->get_translation( 'preloader_label', __( 'Searching...', 'wpsl' ) ),
'noResults' => $wpsl->i18n->get_translation( 'no_results_label', __( 'No results found', 'wpsl' ) ),
'moreInfo' => $wpsl->i18n->get_translation( 'more_label', __( 'More info', 'wpsl' ) ),
'generalError' => $wpsl->i18n->get_translation( 'error_label', __( 'Something went wrong, please try again!', 'wpsl' ) ),
'queryLimit' => $wpsl->i18n->get_translation( 'limit_label', __( 'API usage limit reached', 'wpsl' ) ),
'directions' => $wpsl->i18n->get_translation( 'directions_label', __( 'Directions', 'wpsl' ) ),
'noDirectionsFound' => $wpsl->i18n->get_translation( 'no_directions_label', __( 'No route could be found between the origin and destination', 'wpsl' ) ),
'startPoint' => $wpsl->i18n->get_translation( 'start_label', __( 'Start location', 'wpsl' ) ),
'back' => $wpsl->i18n->get_translation( 'back_label', __( 'Back', 'wpsl' ) ),
'streetView' => $wpsl->i18n->get_translation( 'street_view_label', __( 'Street view', 'wpsl' ) ),
'zoomHere' => $wpsl->i18n->get_translation( 'zoom_here_label', __( 'Zoom here', 'wpsl' ) )
);
wp_localize_script( 'wpsl-js', 'wpslLabels', $labels );
wp_localize_script( 'wpsl-js', 'wpslGeolocationErrors', $this->geolocation_errors() );
} else {
$template = '';
$settings = $base_settings;
}
// Check if we need to overwrite JS settings that are set through the [wpsl] shortcode.
if ( $this->sl_shortcode_atts && isset( $this->sl_shortcode_atts['js'] ) ) {
foreach ( $this->sl_shortcode_atts['js'] as $shortcode_key => $shortcode_val ) {
$settings[$shortcode_key] = $shortcode_val;
}
}
wp_localize_script( 'wpsl-js', 'wpslSettings', apply_filters( 'wpsl_js_settings', $settings ) );
wpsl_create_underscore_templates( $template );
if ( !empty( $this->store_map_data ) ) {
$i = 0;
foreach ( $this->store_map_data as $map ) {
wp_localize_script( 'wpsl-js', 'wpslMap_' . $i, $map );
$i++;
}
}
}
/**
* Get the infobox settings.
*
* @since 2.0.0
* @see http://google-maps-utility-library-v3.googlecode.com/svn/trunk/infobox/docs/reference.html
* @param array $settings The plugin settings used on the front-end in js
* @return array $settings The plugin settings including the infobox settings
*/
public function get_infobox_settings( $settings ) {
$infobox_settings = apply_filters( 'wpsl_infobox_settings', array(
'infoBoxClass' => 'wpsl-infobox',
'infoBoxCloseMargin' => '2px', // The margin can be written in css style, so 2px 2px 4px 2px for top, right, bottom, left
'infoBoxCloseUrl' => '//www.google.com/intl/en_us/mapfiles/close.gif',
'infoBoxClearance' => '40,40',
'infoBoxDisableAutoPan' => 0,
'infoBoxEnableEventPropagation' => 0,
'infoBoxPixelOffset' => '-52,-45',
'infoBoxZindex' => 1500
) );
foreach ( $infobox_settings as $infobox_key => $infobox_setting ) {
$settings[$infobox_key] = $infobox_setting;
}
return $settings;
}
}
} wpml-config.xml 0000644 00000002157 15132722064 0007517 0 ustar 00 <wpml-config>
<admin-texts>
<key name="wpsl_settings">
<key name="editor_country"/>
<key name="start_label"/>
<key name="search_label"/>
<key name="search_btn_label"/>
<key name="preloader_label"/>
<key name="radius_label"/>
<key name="no_results_label"/>
<key name="results_label"/>
<key name="category_label"/>
<key name="category_default_label"/>
<key name="more_label"/>
<key name="directions_label"/>
<key name="no_directions_label"/>
<key name="back_label"/>
<key name="street_view_label"/>
<key name="zoom_here_label"/>
<key name="error_label"/>
<key name="limit_label"/>
<key name="phone_label"/>
<key name="fax_label"/>
<key name="email_label"/>
<key name="url_label"/>
<key name="hours_label"/>
</key>
</admin-texts>
</wpml-config>