'application/gpx+xml', 'kml' => 'application/vnd.google-earth.kml+xml', 'geojson' => 'application/geo+json', ); // Only for users trusted with HTML, as an XML file opened on its own can carry a script. add_filter( 'upload_mimes', function ( $mimes ) { return current_user_can( 'unfiltered_html' ) ? array_merge( (array) $mimes, DELTABREEN_MAPS_FILE_TYPES ) : $mimes; } ); // WordPress reads these files as XML, JSON or text rather than by their own types, and would refuse them without this. add_filter( 'wp_check_filetype_and_ext', function ( $data, $file, $filename, $mimes, $real_mime = null ) { $ext = strtolower( pathinfo( (string) $filename, PATHINFO_EXTENSION ) ); $ok = array( 'text/xml', 'application/xml', 'text/plain', 'application/json', 'text/html' ); if ( empty( $data['ext'] ) && isset( DELTABREEN_MAPS_FILE_TYPES[ $ext ] ) && current_user_can( 'unfiltered_html' ) && ( null === $real_mime || in_array( $real_mime, $ok, true ) ) ) { $data['ext'] = $ext; $data['type'] = DELTABREEN_MAPS_FILE_TYPES[ $ext ]; } return $data; }, 10, 5 ); add_action( 'rest_api_init', function () { // The locations as the embed takes them, for data-maps-pins-url, apps and headless sites, when the site allows it. register_rest_route( 'deltabreen-maps/v1', '/locations', array( 'methods' => 'GET', 'permission_callback' => function () { return ! empty( deltabreen_maps_options()['public_locations'] ); }, 'args' => array( 'category' => array( 'type' => 'string', 'default' => '', 'sanitize_callback' => 'sanitize_text_field', ), ), 'callback' => function ( WP_REST_Request $req ) { $from = deltabreen_maps_location_pins( deltabreen_maps_category_list( $req['category'] ) ); $res = new WP_REST_Response( array( 'pins' => $from['pins'], 'categories' => (object) $from['categories'], 'icons' => (object) $from['icons'], 'glyphs' => (object) $from['glyphs'], ) ); $res->header( 'Cache-Control', 'public, max-age=300' ); return $res; }, ) ); } ); /** * What the map service says about this site's key, asked from this site's own address and kept ten minutes: whether * the service answered, and if so its answer (key, site_allowed, paused, usage). Null with no key. * * @param bool $fresh Ask again rather than use the answer kept. * @return array|null */ function deltabreen_maps_check_key( $fresh = false ) { $key = deltabreen_maps_clean_key( deltabreen_maps_options()['key'] ); if ( '' === $key ) { return null; } $kept = 'deltabreen_maps_check_' . md5( $key ); $was = get_transient( $kept ); if ( ! $fresh && is_array( $was ) ) { return $was; } $res = wp_remote_get( add_query_arg( 'key', rawurlencode( $key ), deltabreen_maps_api_url() . '/api/v1/keys/check' ), array( 'timeout' => 8, 'headers' => array( 'Origin' => home_url() ), ) ); $body = is_wp_error( $res ) || 200 !== (int) wp_remote_retrieve_response_code( $res ) ? null : json_decode( wp_remote_retrieve_body( $res ), true ); $out = is_array( $body ) ? array_merge( $body, array( 'reachable' => true ) ) : array( 'reachable' => false ); set_transient( $kept, $out, 10 * MINUTE_IN_SECONDS ); return $out; } /** * The key's state in a sentence, with its kind: good, recommended or critical. * * @param array|null $check What deltabreen_maps_check_key() answered. * @return array{0: string, 1: string} */ function deltabreen_maps_key_state( $check ) { if ( null === $check ) { return array( 'recommended', __( 'This site has no map key yet: maps do not show until you connect it under Settings → Maps by DeltaBreen.', 'maps-by-deltabreen' ) ); } if ( empty( $check['reachable'] ) ) { return array( 'recommended', __( 'The map service did not answer this site just now. Maps in visitors\' browsers may still work; try again in a few minutes.', 'maps-by-deltabreen' ) ); } $key = $check['key'] ?? ''; if ( 'active' !== $key ) { return array( 'critical', 'secret' === $key ? __( 'The key saved is a secret key, which must never go in a page: connect again or paste a publishable key.', 'maps-by-deltabreen' ) : __( 'The map key saved is unknown or revoked: connect again under Settings → Maps by DeltaBreen.', 'maps-by-deltabreen' ) ); } if ( isset( $check['site_allowed'] ) && false === $check['site_allowed'] ) { /* translators: %s: this site's host name. */ return array( 'critical', sprintf( __( 'The map key does not list %s, so maps here do not show: connect again, or add the site to the key in your dashboard.', 'maps-by-deltabreen' ), (string) wp_parse_url( home_url(), PHP_URL_HOST ) ) ); } if ( ! empty( $check['paused'] ) || 'paused' === ( $check['usage'] ?? '' ) ) { return array( 'critical', __( 'Maps are paused for the rest of the month: the plan\'s map loads are used up. Nothing is charged; a top-up or a larger plan starts them again at once.', 'maps-by-deltabreen' ) ); } if ( 'high' === ( $check['usage'] ?? '' ) ) { return array( 'recommended', __( 'Maps are working, and most of this month\'s map loads are used. Nothing is charged for going over; see your usage to be sure the month is covered.', 'maps-by-deltabreen' ) ); } return array( 'good', __( 'Maps are working, and this month\'s map loads are well within your plan.', 'maps-by-deltabreen' ) ); } add_filter( 'site_status_tests', function ( $tests ) { $tests['direct']['deltabreen_maps_key'] = array( 'label' => __( 'Maps by DeltaBreen', 'maps-by-deltabreen' ), 'test' => function () { list( $status, $words ) = deltabreen_maps_key_state( deltabreen_maps_check_key() ); return array( 'label' => 'good' === $status ? __( 'Maps by DeltaBreen is working', 'maps-by-deltabreen' ) : __( 'Maps by DeltaBreen needs a look', 'maps-by-deltabreen' ), 'status' => $status, 'badge' => array( 'label' => __( 'Maps', 'maps-by-deltabreen' ), 'color' => 'good' === $status ? 'blue' : 'orange', ), 'description' => '
' . esc_html( $words ) . '
', 'actions' => '' . esc_html__( 'Open the map settings', 'maps-by-deltabreen' ) . '
', 'test' => 'deltabreen_maps_key', ); }, ); return $tests; } ); add_action( 'wp_dashboard_setup', function () { if ( current_user_can( 'manage_options' ) ) { wp_add_dashboard_widget( 'deltabreen_maps_status', __( 'Maps by DeltaBreen', 'maps-by-deltabreen' ), 'deltabreen_maps_dashboard_widget' ); } } ); /** The dashboard widget: the key's state, how far the month's map loads have gone, and where to look further. */ function deltabreen_maps_dashboard_widget() { list( $status, $words ) = deltabreen_maps_key_state( deltabreen_maps_check_key() ); $colour = array( 'good' => '#00a32a', 'recommended' => '#dba617', 'critical' => '#d63638', ); ?>'Complianz', 'borlabs' => 'Borlabs Cookie', 'cookieyes' => 'CookieYes', 'realcookiebanner' => 'Real Cookie Banner', ); /** The cookie banner this site runs, as each plugin announces itself when active; empty for none of them. */ function deltabreen_maps_cookie_tool_found() { if ( defined( 'cmplz_free' ) || defined( 'cmplz_premium' ) || class_exists( 'COMPLIANZ' ) ) { return 'complianz'; } if ( defined( 'BORLABS_COOKIE_VERSION' ) ) { return 'borlabs'; } if ( defined( 'CLI_VERSION' ) ) { return 'cookieyes'; } return defined( 'RCB_VERSION' ) ? 'realcookiebanner' : ''; } /** The cookie banner maps follow: the one chosen, else the one this site runs; empty for none. */ function deltabreen_maps_cookie_tool() { $chosen = (string) deltabreen_maps_options()['cookie_tool']; if ( 'none' === $chosen ) { return ''; } return isset( DELTABREEN_MAPS_COOKIE_TOOLS[ $chosen ] ) ? $chosen : deltabreen_maps_cookie_tool_found(); } /** The category or service a banner gives maps under, unless the site names its own. */ function deltabreen_maps_cookie_default( $tool ) { $defaults = array( 'complianz' => 'marketing', 'borlabs' => 'deltabreen-maps', 'cookieyes' => 'functional', 'realcookiebanner' => 'deltabreen-maps', ); return $defaults[ $tool ] ?? ''; } /** * On a page with a map that asks first: let the site's cookie banner answer for it, so maps start once the visitor * agrees there; the map's own "always show" choice gives way to the banner's. */ function deltabreen_maps_follow_banner() { static $done = false; $tool = deltabreen_maps_cookie_tool(); if ( $done || '' === $tool ) { return; } $done = true; $config = array( 'tool' => $tool, 'category' => '' !== deltabreen_maps_options()['cookie_category'] ? deltabreen_maps_options()['cookie_category'] : deltabreen_maps_cookie_default( $tool ), ); wp_enqueue_script( 'deltabreen-maps-consent' ); wp_add_inline_script( 'deltabreen-maps-consent', 'window.deltabreenMapsConsent = ' . wp_json_encode( $config, JSON_HEX_TAG | JSON_HEX_AMP ) . '; try { localStorage.removeItem("deltabreen-maps-consent"); } catch (e) {}', 'before' ); wp_register_style( 'deltabreen-maps-consent', false, array(), DELTABREEN_MAPS_VERSION ); wp_enqueue_style( 'deltabreen-maps-consent' ); wp_add_inline_style( 'deltabreen-maps-consent', '.deltabreen-map [data-maps-consent-box] label { display: none; }' ); } // At init: a block theme renders a page's blocks before wp_enqueue_scripts, and the bridge's settings go with it. add_action( 'init', function () { wp_register_script( 'deltabreen-maps-consent', plugins_url( 'assets/consent-bridge.js', __FILE__ ), array(), DELTABREEN_MAPS_VERSION, array( 'in_footer' => true ) ); } );