Commit realizado el 12:13:52 08-04-2024

This commit is contained in:
Pagina Web Monito
2024-04-08 12:13:55 -04:00
commit 0c33094de9
7815 changed files with 1365694 additions and 0 deletions

View File

@@ -0,0 +1 @@
.rank-math-business-wrapper .rank-math-directions-wrapper .rank-math-directions-result{display:none}.rank-math-business-wrapper .rank-math-directions-wrapper.show .rank-math-directions-result{display:block}

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
(()=>{"use strict";var t={n:e=>{var n=e&&e.__esModule?()=>e.default:()=>e;return t.d(n,{a:n}),n},d:(e,n)=>{for(var o in n)t.o(n,o)&&!t.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:n[o]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e)};const e=jQuery;var n=t.n(e);const o=lodash,r=wp.i18n;function i(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",n=rankMath.links[t]||"";if(!n)return"#";if(!e)return n;var o={utm_source:"Plugin",utm_medium:encodeURIComponent(e),utm_campaign:"WP"};return n+"?"+Object.keys(o).map((function(t){return"".concat(t,"=").concat(o[t])})).join("&")}function a(t){return a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},a(t)}function s(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,(r=o.key,i=void 0,i=function(t,e){if("object"!==a(t)||null===t)return t;var n=t[Symbol.toPrimitive];if(void 0!==n){var o=n.call(t,e||"default");if("object"!==a(o))return o;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===e?String:Number)(t)}(r,"string"),"symbol"===a(i)?i:String(i)),o)}var r,i}var u=function(){function t(){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.pointers=this.getPointers(),this.showPointer=this.showPointer.bind(this),this.init()}var e,a,u;return e=t,(a=[{key:"init",value:function(){var t=this;(0,o.forEach)(this.pointers,(function(e,n){return t.showPointer(n),!1})),n()(".rank-math-toolbar-score").parent().hasClass("is-pressed")||n()(".rank-math-toolbar-score").parent().trigger("click")}},{key:"showPointer",value:function(t){var e=this,o=this.pointers[t],i=n().extend(o.options,{pointerClass:"wp-pointer rm-pointer",close:function(){o.next&&e.showPointer(o.next)},buttons:function(t,e){var o="wp-pointer-3"===e.pointer[0].id?(0,r.__)("Finish","rank-math-pro"):(0,r.__)("Next","rank-math-pro"),i=n()('<a class="close" href="#">'+(0,r.__)("Dismiss","rank-math-pro")+"</a>"),a=n()('<a class="button button-primary" href="#">'+o+"</a>"),s=n()('<div class="rm-pointer-buttons" />');return i.on("click.pointer",(function(t){t.preventDefault(),e.element.pointer("destroy")})),a.on("click.pointer",(function(t){t.preventDefault(),e.element.pointer("close")})),s.append(i),s.append(a),s}}),a=n()(o.target).pointer(i);a.pointer("open"),o.next_trigger&&n()(o.next_trigger.target).on(o.next_trigger.event,(function(){setTimeout((function(){a.pointer("close")}),400)}))}},{key:"getPointers",value:function(){return{title:{target:".editor-post-title__input",next:"schema",options:{content:"<h3>"+(0,r.__)("Local Business Name","rank-math-pro")+"</h3><p>"+(0,r.__)("Give your business's new location a name here. This field is required and will be visible to users.","rank-math-pro")+"</p>"}},schema:{target:".components-tab-panel__tabs-item.rank-math-schema-tab",next:"content",options:{content:"<h3>"+(0,r.__)("Local Business Schema","rank-math-pro")+"</h3><p>"+(0,r.__)('Add your local business\'s details here with "Local Business" Schema Markup in order to be eligible for local SERP features.',"rank-math-pro")+"</p>",position:{edge:"right",align:"left"}}},content:{target:".is-root-container",next:"submitdiv",options:{content:"<h3>"+(0,r.__)("Show Business Information","rank-math-pro")+"</h3><p>"+(0,r.sprintf)((0,r.__)("Make sure to add the Local Business Block or %s to display your business data.","rank-math-pro"),'<a href="'+i("location-data-shortcode","Show Business Information")+'" target="_blank">[rank_math_local] shortcode</a>')+"</p>",position:{edge:"bottom",align:"middle"}}},submitdiv:{target:".editor-post-publish-button__button",next:"",options:{content:"<h3>"+(0,r.__)("Publish your location!","rank-math-pro")+"</h3><p>"+(0,r.__)("When you're done editing, don't forget to hit \"publish\" to create this location.","rank-math-pro")+"</p>"}}}}}])&&s(e.prototype,a),u&&s(e,u),Object.defineProperty(e,"prototype",{writable:!1}),t}();n()(window).on("load",(function(){new u}))})();

View File

@@ -0,0 +1,87 @@
<?php
/**
* The Local_Seo Module
*
* @since 1.0.0
* @package RankMath
* @subpackage RankMathPro
* @author Rank Math <support@rankmath.com>
*/
namespace RankMathPro\Local_Seo;
use RankMath\KB;
use RankMath\Helper;
use RankMath\Traits\Hooker;
use RankMath\Admin\Admin_Helper;
use RankMath\Sitemap\Router;
defined( 'ABSPATH' ) || exit;
/**
* Admin class.
*/
class Admin {
use Hooker;
/**
* The Constructor.
*/
public function __construct() {
$this->filter( 'rank_math/settings/title', 'add_settings' );
$this->filter( 'rank_math/settings/sitemap', 'add_sitemap_settings', 11 );
$this->filter( 'rank_math/settings/snippet/types', 'add_local_business_schema_type', 10, 2 );
}
/**
* Add module settings into general optional panel.
*
* @param array $tabs Array of option panel tabs.
*
* @return array
*/
public function add_settings( $tabs ) {
$tabs['local']['file'] = dirname( __FILE__ ) . '/views/titles-options.php';
return $tabs;
}
/**
* Add module settings into general optional panel.
*
* @param array $tabs Array of option panel tabs.
*
* @return array
*/
public function add_sitemap_settings( $tabs ) {
$sitemap_url = Router::get_base_url( 'locations.kml' );
$tabs['kml-file'] = [
'icon' => 'rm-icon rm-icon-local-seo',
'title' => esc_html__( 'Local Sitemap', 'rank-math-pro' ),
'desc' => wp_kses_post( sprintf( __( 'KML is a file format used to display geographic data in an Earth browser such as Google Earth. More information: <a href="%s" target="_blank">Locations KML</a>', 'rank-math-pro' ), KB::get( 'kml-sitemap', 'Options Panel Sitemap Local Tab' ) ) ),
'file' => dirname( __FILE__ ) . '/views/sitemap-settings.php',
/* translators: KML File Url */
'after_row' => '<div class="notice notice-alt notice-info info inline rank-math-notice"><p>' . sprintf( esc_html__( 'Your Locations KML file can be found here: %s', 'rank-math-pro' ), '<a href="' . $sitemap_url . '" target="_blank">' . $sitemap_url . '</a>' ) . '</p></div>',
];
return $tabs;
}
/**
* Add Pro schema types in Schema settings choices array.
*
* @param array $types Schema types.
* @param string $post_type Post type.
*/
public function add_local_business_schema_type( $types, $post_type ) {
if ( 'rank_math_locations' === $post_type ) {
$types = [
'off' => esc_html__( 'None', 'rank-math-pro' ),
'LocalBusiness' => esc_html__( 'Local Business', 'rank-math-pro' ),
];
}
return $types;
}
}

View File

@@ -0,0 +1,199 @@
<?php
/**
* The Local_Seo Module
*
* @since 1.0.0
* @package RankMath
* @subpackage RankMathPro
* @author Rank Math <support@rankmath.com>
*/
namespace RankMathPro\Local_Seo;
use RankMath\Helper;
use RankMath\Post;
use RankMath\Traits\Hooker;
use RankMath\Schema\DB;
defined( 'ABSPATH' ) || exit;
/**
* Frontend class.
*/
class Frontend {
use Hooker;
/**
* The Constructor.
*/
public function __construct() {
$this->action( 'rank_math/json_ld', 'add_location_schema', 100, 2 );
$this->action( 'rank_math/head', 'add_location_tags', 90 );
new Search();
}
/**
* Add Locations Metatags to head.
*/
public function add_location_tags() {
if ( ! is_singular( 'rank_math_locations' ) ) {
return;
}
$schema = DB::get_schemas( Post::get_page_id() );
if ( empty( $schema ) ) {
return;
}
$schema = current( $schema );
$meta_tags = [
'placename' => ! empty( $schema['address']['addressLocality'] ) ? $schema['address']['addressLocality'] : '',
'position' => ! empty( $schema['geo']['latitude'] ) ? $schema['geo']['latitude'] . ';' . $schema['geo']['longitude'] : '',
'region' => ! empty( $schema['address']['addressCountry'] ) ? $schema['address']['addressCountry'] : '',
];
foreach ( $meta_tags as $name => $value ) {
if ( ! $value ) {
continue;
}
printf( '<meta name="geo.%1$s" content="%2$s" />' . "\n", esc_attr( $name ), esc_attr( $value ) );
}
}
/**
* Add Locations Schema.
*
* @param array $data Array of json-ld data.
* @param JsonLD $jsonld Instance of jsonld.
*
* @return array
*/
public function add_location_schema( $data, $jsonld ) {
if ( ! is_singular( 'rank_math_locations' ) ) {
return $data;
}
global $post;
$schemas = DB::get_schemas( $post->ID );
$schema_key = key( $schemas );
if ( ! isset( $data[ $schema_key ] ) ) {
return $data;
}
$entity = $data[ $schema_key ];
$this->add_place_entity( $data, $entity, $jsonld, ! empty( $schemas[ $schema_key ]['metadata']['open247'] ) );
$this->validate_publisher_data( $data, $jsonld );
$data[ $schema_key ] = $this->validate_locations_data( $entity, $data );
return $data;
}
/**
* Add Schema Place entity on Rank Math locations posts.
*
* @param array $data Array of json-ld data.
* @param array $entity Location data.
* @param JsonLD $jsonld Instance of jsonld.
* @param bool $is_open247 Whether business is open 24*7.
*/
private function add_place_entity( &$data, &$entity, $jsonld, $is_open247 ) {
$properties = [];
foreach ( [ 'openingHoursSpecification', 'geo' ] as $property ) {
if ( isset( $entity[ $property ] ) ) {
$properties[ $property ] = $entity[ $property ];
}
}
if ( isset( $entity['address'] ) ) {
$properties['address'] = $entity['address'];
}
if ( $is_open247 ) {
$properties['openingHoursSpecification'] = [
'@type' => 'OpeningHoursSpecification',
'dayOfWeek' => [
'Monday',
'Tuesday',
'Wednesday',
'Thursday',
'Friday',
'Saturday',
'Sunday',
],
'opens' => '00:00',
'closes' => '23:59',
];
}
if ( empty( $properties ) ) {
return;
}
$data['place'] = array_merge(
[
'@type' => 'Place',
'@id' => $jsonld->parts['canonical'] . '#place',
],
$properties
);
}
/**
* Change Publisher Data when multiple locations option is enabled.
*
* @param array $data Array of json-ld data.
* @param JsonLD $jsonld Instance of jsonld.
*
* @return array
*/
private function validate_publisher_data( &$data, $jsonld ) {
if ( empty( $data['publisher'] ) ) {
return;
}
$data['publisher'] = [
'@type' => 'Organization',
'@id' => $data['publisher']['@id'],
'name' => $jsonld->get_website_name(),
'logo' => [
'@type' => 'ImageObject',
'url' => Helper::get_settings( 'titles.knowledgegraph_logo' ),
],
];
}
/**
* Validate Locations data before adding it in ld+json.
*
* @param array $entity Location data.
* @param array $data Array of json-ld data.
*
* @return array
*/
private function validate_locations_data( $entity, $data ) {
// Remove invalid properties.
foreach ( [ 'isPartOf', 'publisher', 'inLanguage' ] as $property ) {
if ( isset( $entity[ $property ] ) ) {
unset( $entity[ $property ] );
}
}
// Add Parent Organization.
if (
! empty( $data['publisher'] ) &&
Helper::get_settings( 'titles.same_organization_locations', false )
) {
$entity['parentOrganization'] = [ '@id' => $data['publisher']['@id'] ];
}
// Add reference to the place entity.
if ( isset( $data['place'] ) ) {
$entity['location'] = [ '@id' => $data['place']['@id'] ];
}
return $entity;
}
}

View File

@@ -0,0 +1,96 @@
<?php
/**
* The KML File
*
* @since 2.1.2
* @package RankMath
* @subpackage RankMathPro\Local_Seo
* @author Rank Math <support@rankmath.com>
*/
namespace RankMathPro\Local_Seo;
use RankMath\Helper;
use RankMath\Traits\Hooker;
use RankMath\Sitemap\Cache_Watcher;
use RankMath\Schema\DB;
defined( 'ABSPATH' ) || exit;
/**
* KML_File class.
*/
class KML_File {
use Hooker;
/**
* The Constructor.
*/
public function __construct() {
$this->filter( 'rank_math/sitemap/locations/data', 'add_location_data' );
$this->action( 'save_post_rank_math_locations', 'save_post' );
}
/**
* Check for relevant post type before invalidation.
*
* @param int $post_id Post ID to possibly invalidate for.
*/
public function save_post( $post_id ) {
if (
wp_is_post_revision( $post_id ) ||
false === Helper::is_post_indexable( $post_id )
) {
return false;
}
Cache_Watcher::invalidate( 'locations' );
}
/**
* Generate the KML file contents.
*
* @return string $kml KML file content.
*/
public function add_location_data() {
$rm_locations = get_posts(
[
'post_type' => 'rank_math_locations',
'numberposts' => -1,
]
);
if ( empty( $rm_locations ) ) {
return [];
}
$locations = [];
foreach ( $rm_locations as $rm_location ) {
$locations_data = current( DB::get_schemas( $rm_location->ID ) );
if ( empty( $locations_data ) ) {
continue;
}
rank_math()->variables->setup();
$name = ! empty( $locations_data['name'] ) ? $locations_data['name'] : '%seo_title%';
$description = ! empty( $locations_data['description'] ) ? $locations_data['description'] : '%seo_description%';
$address = '';
if ( ! empty( $locations_data['address'] ) && isset( $locations_data['address']['@type'] ) ) {
unset( $locations_data['address']['@type'] );
$address = $locations_data['address'];
}
$locations[] = [
'name' => Helper::replace_vars( $name, $rm_location ),
'description' => Helper::replace_vars( $description, $rm_location ),
'email' => ! empty( $locations_data['email'] ) ? Helper::replace_vars( $locations_data['email'], $rm_location ) : '',
'phone' => ! empty( $locations_data['telephone'] ) ? Helper::replace_vars( $locations_data['telephone'], $rm_location ) : '',
'url' => get_the_permalink( $rm_location ),
'address' => ! empty( $locations_data['address'] ) ? $locations_data['address'] : '',
'coords' => ! empty( $locations_data['geo'] ) ? $locations_data['geo'] : '',
];
}
return $locations;
}
}

View File

@@ -0,0 +1,315 @@
<?php
/**
* The Local_Seo Module
*
* @since 1.0.0
* @package RankMath
* @subpackage RankMathPro
* @author Rank Math <support@rankmath.com>
*/
namespace RankMathPro\Local_Seo;
use RankMath\Helper;
use RankMath\Traits\Hooker;
use RankMath\Sitemap\Cache_Watcher;
defined( 'ABSPATH' ) || exit;
/**
* Local_Seo class.
*/
class Local_Seo {
use Hooker;
/**
* Post Singular Name.
*
* @var string
*/
private $post_singular_name = 'Location';
/**
* Post Type.
*
* @var string
*/
private $post_type = 'rank_math_locations';
/**
* The Constructor.
*/
public function __construct() {
$this->action( 'init', 'init' );
$this->action( 'rank_math/schema/update', 'update_post_schema_info', 10, 2 );
$this->action( 'save_post', 'invalidate_cache' );
$this->filter( 'classic_editor_enabled_editors_for_post_type', 'force_block_editor', 20, 2 );
$this->filter( 'rank_math/sitemap/locations', 'add_kml_file' );
$this->filter( "manage_{$this->post_type}_posts_columns", 'posts_columns' );
$this->filter( "manage_{$this->post_type}_posts_custom_column", 'posts_custom_column', 10, 2 );
$this->filter( "bulk_actions-edit-{$this->post_type}", 'post_bulk_actions', 20 );
$this->includes();
}
/**
* Update post info for analytics.
*
* @param int $object_id Object ID.
* @param array $schemas Schema data.
* @param string $object_type Object type.
*/
public function update_post_schema_info( $object_id, $schemas, $object_type = 'post' ) {
if ( 'post' !== $object_type || 'rank_math_locations' !== get_post_type( $object_id ) ) {
return;
}
$schema = current( $schemas );
if ( ! isset( $schema['geo'], $schema['geo']['latitude'], $schema['geo']['longitude'] ) ) {
return;
}
update_post_meta( $object_id, 'rank_math_local_business_latitide', $schema['geo']['latitude'] );
update_post_meta( $object_id, 'rank_math_local_business_longitude', $schema['geo']['longitude'] );
}
/**
* Intialize.
*/
public function init() {
if ( ! Helper::get_settings( 'titles.use_multiple_locations', false ) ) {
return;
}
$this->post_singular_name = Helper::get_settings( 'titles.locations_post_type_label', 'Location' );
$this->register_location_post_type();
$this->register_location_taxonomy();
}
/**
* Filters the editors that are enabled for the post type.
*
* @param array $editors Associative array of the editors and whether they are enabled for the post type.
* @param string $post_type The post type.
*/
public function force_block_editor( $editors, $post_type ) {
if ( 'rank_math_locations' !== $post_type || ! $this->do_filter( 'schema/cpt_force_gutenberg', true ) ) {
return $editors;
}
$editors['classic_editor'] = false;
return $editors;
}
/**
* Add Locations KML file in the sitemap
*/
public function add_kml_file() {
return Helper::get_settings( 'sitemap.local_sitemap', true );
}
/**
* Include required files.
*/
private function includes() {
if ( is_admin() ) {
new Admin();
new RM_Pointers();
return;
}
if ( Helper::get_settings( 'titles.use_multiple_locations', false ) ) {
new Frontend();
new Location_Shortcode();
new KML_File();
}
}
/**
* Register Locations post type.
*/
private function register_location_post_type() {
$plural_label = Helper::get_settings( 'titles.locations_post_type_plural_label', 'RM Locations' );
$post_type_slug = Helper::get_settings( 'titles.locations_post_type_base', 'locations' );
$labels = [
'name' => $this->post_singular_name,
'singular_name' => $this->post_singular_name,
'menu_name' => $plural_label,
/* translators: Post Type Plural Name */
'all_items' => sprintf( esc_html__( 'All %s', 'rank-math-pro' ), $plural_label ),
/* translators: Post Type Singular Name */
'add_new_item' => sprintf( esc_html__( 'Add New %s', 'rank-math-pro' ), $this->post_singular_name ),
/* translators: Post Type Singular Name */
'new_item' => sprintf( esc_html__( 'New %s', 'rank-math-pro' ), $this->post_singular_name ),
/* translators: Post Type Singular Name */
'edit_item' => sprintf( esc_html__( 'Edit %s', 'rank-math-pro' ), $this->post_singular_name ),
/* translators: Post Type Singular Name */
'update_item' => sprintf( esc_html__( 'Update %s', 'rank-math-pro' ), $this->post_singular_name ),
/* translators: Post Type Singular Name */
'view_item' => sprintf( esc_html__( 'View %s', 'rank-math-pro' ), $this->post_singular_name ),
/* translators: Post Type Plural Name */
'view_items' => sprintf( esc_html__( 'View %s', 'rank-math-pro' ), $plural_label ),
/* translators: Post Type Singular Name */
'search_items' => sprintf( esc_html__( 'Search %s', 'rank-math-pro' ), $this->post_singular_name ),
/* translators: Post Type Singular Name */
'not_found' => sprintf( esc_html__( 'No %s found.', 'rank-math-pro' ), $plural_label ),
/* translators: Post Type Singular Name */
'not_found_in_trash' => sprintf( esc_html__( 'No %s found in Trash.', 'rank-math-pro' ), $plural_label ),
/* translators: Post Type Singular Name */
'item_published' => sprintf( esc_html__( '%s published.', 'rank-math-pro' ), $this->post_singular_name ),
/* translators: Post Type Singular Name */
'item_published_privately' => sprintf( esc_html__( '%s published privately.', 'rank-math-pro' ), $this->post_singular_name ),
/* translators: Post Type Singular Name */
'item_reverted_to_draft' => sprintf( esc_html__( '%s reverted to draft.', 'rank-math-pro' ), $this->post_singular_name ),
/* translators: Post Type Singular Name */
'item_scheduled' => sprintf( esc_html__( '%s scheduled.', 'rank-math-pro' ), $this->post_singular_name ),
/* translators: Post Type Singular Name */
'item_updated' => sprintf( esc_html__( '%s updated.', 'rank-math-pro' ), $this->post_singular_name ),
];
$capability = 'rank_math_general';
$args = [
'label' => $this->post_singular_name,
'labels' => $labels,
'public' => true,
'publicly_queryable' => true,
'show_ui' => true,
'hierarchical' => false,
'has_archive' => $post_type_slug,
'menu_icon' => 'dashicons-location',
'query_var' => true,
'show_in_rest' => true,
'rest_base' => 'rank-math-locations',
'supports' => [ 'title', 'editor', 'excerpt', 'author', 'thumbnail', 'revisions', 'custom-fields', 'page-attributes', 'publicize' ],
'rewrite' => [
'slug' => $post_type_slug,
'with_front' => $this->filter( 'locations/front', true ),
],
'capabilities' => [
'edit_post' => $capability,
'read_post' => $capability,
'delete_post' => $capability,
'edit_posts' => $capability,
'edit_others_posts' => $capability,
'publish_posts' => $capability,
'read_private_posts' => $capability,
'create_posts' => $capability,
],
];
register_post_type( $this->post_type, $args );
}
/**
* Register Locations Category taxonomy.
*/
private function register_location_taxonomy() {
$category_slug = esc_html( Helper::get_settings( 'titles.locations_category_base', 'locations-category' ) );
$labels = [
/* translators: Post Type Singular Name */
'name' => sprintf( esc_html__( '%s categories', 'rank-math-pro' ), $this->post_singular_name ),
/* translators: Post Type Singular Name */
'singular_name' => sprintf( esc_html__( '%s category', 'rank-math-pro' ), $this->post_singular_name ),
/* translators: Post Type Singular Name */
'all_items' => sprintf( esc_html__( 'All %s categories', 'rank-math-pro' ), $this->post_singular_name ),
/* translators: Post Type Singular Name */
'edit_item' => sprintf( esc_html__( 'Edit %s category', 'rank-math-pro' ), $this->post_singular_name ),
/* translators: Post Type Singular Name */
'update_item' => sprintf( esc_html__( 'Update %s category', 'rank-math-pro' ), $this->post_singular_name ),
/* translators: Post Type Singular Name */
'add_new_item' => sprintf( esc_html__( 'Add New %s category', 'rank-math-pro' ), $this->post_singular_name ),
/* translators: Post Type Singular Name */
'new_item_name' => sprintf( esc_html__( 'New %s category', 'rank-math-pro' ), $this->post_singular_name ),
/* translators: Post Type Singular Name */
'menu_name' => sprintf( esc_html__( '%s categories', 'rank-math-pro' ), $this->post_singular_name ),
'search_items' => esc_html__( 'Search categories', 'rank-math-pro' ),
'parent_item' => esc_html__( 'Parent Category', 'rank-math-pro' ),
'parent_item_colon' => esc_html__( 'Parent Category:', 'rank-math-pro' ),
];
$args = [
'hierarchical' => true,
'labels' => $labels,
'show_ui' => true,
'show_admin_column' => true,
'query_var' => true,
'show_in_rest' => true,
'rewrite' => [ 'slug' => $category_slug ],
];
register_taxonomy( 'rank_math_location_category', [ $this->post_type ], $args );
}
/**
* Check for relevant post type before invalidation.
*
* @param int $post_id Post ID to possibly invalidate for.
*/
public function invalidate_cache( $post_id ) {
if ( get_post_type( $post_id ) !== $this->post_type ) {
return false;
}
Cache_Watcher::clear( [ 'locations' ] );
}
/**
* Add custom columns for post type.
*
* @param array $columns Current columns.
*
* @return array
*/
public function posts_columns( $columns ) {
$columns['address'] = __( 'Address', 'rank-math-pro' );
$columns['telephone'] = __( 'Phone', 'rank-math-pro' );
return $columns;
}
/**
* Add the content in the custom columns.
*
* @param string $column Column name.
* @param int $post_id Post ID.
*
* @return void
*/
public function posts_custom_column( $column, $post_id ) {
$schemas = \RankMath\Schema\DB::get_schemas( $post_id );
if ( empty( $schemas ) ) {
return;
}
$schema = reset( $schemas );
if ( empty( $schema[ $column ] ) ) {
return;
}
switch ( $column ) {
case 'address':
unset( $schema['address']['@type'] );
echo esc_html( join( ' ', $schema['address'] ) );
break;
case 'telephone':
echo esc_html( $schema['telephone'] );
break;
}
}
/**
* Remove unneeded bulk actions.
*
* @param array $actions Actions.
* @return array New actions.
*/
public function post_bulk_actions( $actions ) {
unset( $actions['rank_math_bulk_schema_none'], $actions['rank_math_bulk_schema_default'] );
return $actions;
}
}

View File

@@ -0,0 +1,567 @@
<?php
/**
* The Schema Shortcode
*
* @since 1.0.24
* @package RankMath
* @subpackage RankMath\Schema
* @author Rank Math <support@rankmath.com>
*/
namespace RankMathPro\Local_Seo;
use RankMath\Helper;
use RankMath\Schema\DB;
use RankMath\Traits\Hooker;
use RankMath\Traits\Shortcode;
use MyThemeShop\Helpers\Str;
defined( 'ABSPATH' ) || exit;
/**
* Snippet_Shortcode class.
*/
class Location_Shortcode {
use Hooker, Shortcode;
/**
* Shortcode attributes.
*
* @var array
*/
public $atts = [];
/**
* Address Instance.
*
* @var Address
*/
public $address;
/**
* Opening Hours Instance.
*
* @var Opening_Hours
*/
public $opening_hours;
/**
* Map Instance.
*
* @var Map
*/
public $map;
/**
* Store Locator Instance.
*
* @var Store_Locator
*/
public $store_locator;
/**
* API Key.
*
* @var string
*/
public $api_key;
/**
* The Constructor.
*/
public function __construct() {
$this->address = new Address();
$this->opening_hours = new Opening_Hours();
$this->map = new Map();
$this->store_locator = new Store_Locator();
$this->api_key = Helper::get_settings( 'titles.maps_api_key' );
// Add Yoast compatibility shortcodes.
$this->add_shortcode( 'wpseo_all_locations', 'yoast_locations' );
$this->add_shortcode( 'wpseo_storelocator', 'yoast_store_locator' );
$this->add_shortcode( 'wpseo_opening_hours', 'yoast_opening_hours' );
$this->add_shortcode( 'wpseo_map', 'yoast_map' );
$this->add_shortcode( 'rank_math_local', 'local_shortcode' );
$this->action( 'wp_enqueue_scripts', 'enqueue' );
$this->action( 'wp_enqueue_scripts', 'enqueue' );
if ( ! function_exists( 'register_block_type' ) ) {
return;
}
register_block_type(
'rank-math/local-business',
[
'render_callback' => [ $this, 'local_shortcode' ],
'attributes' => $this->get_attributes(),
]
);
}
/**
* Enqueue Map scripts.
*/
public function enqueue() {
if ( ! $this->api_key ) {
return;
}
wp_register_script( 'rank-math-google-maps', '//maps.googleapis.com/maps/api/js?&key=' . rawurlencode( $this->api_key ), [], rank_math_pro()->version, true );
wp_register_script( 'rank-math-google-maps-cluster', 'https://developers-dot-devsite-v2-prod.appspot.com/maps/documentation/javascript/examples/markerclusterer/markerclustererplus@4.0.1.min.js', [], rank_math_pro()->version, true );
wp_register_script( 'rank-math-local', RANK_MATH_PRO_URL . 'includes/modules/local-seo/assets/js/rank-math-local.js', [ 'jquery', 'lodash', 'rank-math-google-maps', 'rank-math-google-maps-cluster' ], rank_math_pro()->version, true );
}
/**
* Location shortcode.
*
* @param array $atts Optional. Shortcode arguments.
*
* @return string Shortcode output.
*/
public function local_shortcode( $atts ) {
$defaults = [];
foreach ( $this->get_attributes() as $key => $attribute ) {
$defaults[ $key ] = $attribute['default'];
}
$this->atts = shortcode_atts(
$defaults,
$atts,
'rank_math_local'
);
if ( ! $this->api_key && is_user_logged_in() && in_array( $this->atts['type'], [ 'store-locator', 'map' ], true ) ) {
return sprintf(
/* Translators: %s expands to General Settings Link. */
esc_html__( 'This page can\'t load Google Maps correctly. Please add %s.', 'rank-math-pro' ),
'<a href="' . Helper::get_admin_url( 'options-titles#setting-panel-local' ) . '" target="_blank">' . esc_html__( 'API Key', 'rank-math-pro' ) . '</a>'
);
}
wp_enqueue_style( 'rank-math-local-business', RANK_MATH_PRO_URL . 'includes/modules/local-seo/assets/css/local-business.css', null, rank_math_pro()->version );
if ( 'store-locator' === $this->atts['type'] ) {
return $this->store_locator->get_data( $this );
}
return $this->get_shortcode_data();
}
/**
* Yoast Map compatibility functionality.
*
* @param array $atts Array of arguments.
* @return string
*/
public function yoast_map( $atts ) {
$atts['type'] = 'map';
return $this->yoast_locations( $atts );
}
/**
* Yoast Opening Hours compatibility functionality.
*
* @param array $atts Array of arguments.
* @return string
*/
public function yoast_opening_hours( $atts ) {
$atts['type'] = 'opening-hours';
return $this->yoast_locations( $atts );
}
/**
* Yoast Store Locator compatibility functionality.
*
* @param array $atts Array of arguments.
* @return string
*/
public function yoast_store_locator( $atts ) {
$atts['type'] = 'store-locator';
return $this->yoast_locations( $atts );
}
/**
* Yoast locations compatibility functionality.
*
* @param array $args Array of arguments.
* @return string
*/
public function yoast_locations( $args ) {
$defaults = [
'id' => '',
'number' => -1,
'type' => 'address',
'term_id' => '',
'orderby' => 'menu_order title',
'order' => 'ASC',
'show_state' => true,
'show_country' => true,
'show_phone' => true,
'show_phone_2' => true,
'show_fax' => true,
'show_email' => true,
'show_url' => false,
'show_logo' => false,
'show_opening_hours' => false,
'hide_closed' => false,
'oneline' => false,
'echo' => false,
'comment' => '',
'radius' => 10,
'max_number' => '',
'show_radius' => false,
'show_nearest_suggestion' => true,
'show_map' => true,
'show_filter' => false,
'map_width' => '100%',
'scrollable' => true,
'draggable' => true,
'marker_clustering' => false,
'map_style' => 'ROADMAP',
'show_route' => true,
'show_route_label' => '',
'show_category_filter' => false,
'height' => 300,
'zoom' => -1,
'show_open_label' => false,
'show_days' => '',
'center' => '',
'default_show_infowindow' => false,
];
$new_atts = [];
$atts = shortcode_atts( $defaults, $args, 'wpseo_local_show_all_locations' );
$data = [
'type' => 'type',
'id' => 'locations',
'number' => 'limit',
'max_number' => 'limit',
'term_id' => 'terms',
'show_state' => 'show_state',
'show_country' => 'show_country',
'show_phone' => 'show_telephone',
'show_phone_2' => 'show_secondary_number',
'show_fax' => 'show_fax',
'show_email' => 'show_email',
'show_url' => 'show_url',
'show_logo' => 'show_logo',
'show_opening_hours' => 'show_opening_hours',
'show_days' => 'show_days',
'hide_closed' => 'hide_closed_days',
'oneline' => 'show_on_one_line',
'comment' => 'opening_hours_note',
'radius' => 'search_radius',
'show_radius' => 'show_radius',
'show_nearest_suggestion' => 'show_nearest_location',
'show_map' => 'show_map',
'show_filter' => 'show_category_filter',
'map_width' => 'map_width',
'map_height' => 'map_height',
'center' => 'map_center',
'zoom' => 'zoom_level',
'scrollable' => 'allow_scrolling',
'draggable' => 'allow_dragging',
'marker_clustering' => 'show_marker_clustering',
'map_style' => 'map_style',
'show_route' => 'show_route_planner',
'show_route_label' => 'route_label',
'show_category_filter' => 'show_category_filter',
'default_show_infowindow' => 'show_infowindow',
];
foreach ( $atts as $key => $value ) {
if ( ! isset( $data[ $key ] ) ) {
continue;
}
$new_atts[ $data[ $key ] ] = $value;
}
return $this->local_shortcode( $new_atts );
}
/**
* Get Location Shortcode data.
*
* @return string Shortcode data.
*/
private function get_shortcode_data() {
$args = [
'post_type' => 'rank_math_locations',
'numberposts' => empty( $this->atts['limit'] ) ? -1 : (int) $this->atts['limit'],
'include' => (int) $this->atts['locations'],
];
if ( ! empty( $this->atts['terms'] ) ) {
$args['tax_query'] = [
[
'taxonomy' => 'rank_math_location_category',
'field' => 'term_id',
'terms' => $this->atts['terms'],
],
];
}
/**
* Filter to change Locations query args.
*
* @param array $args Arguments to retrieve locations.
* @return array $args.
*/
$args = $this->do_filter( 'location_args', $args );
$locations = get_posts( $args );
if ( empty( $locations ) ) {
return esc_html__( 'Sorry, no locations were found.', 'rank-math-pro' );
}
if ( 'map' === $this->atts['type'] ) {
return $this->map->get_data( $this, $locations );
}
$data = '';
foreach ( $locations as $location ) {
$schema = DB::get_schemas( $location->ID );
if ( empty( $schema ) ) {
continue;
}
$schema = current( $this->replace_variables( $schema, $location ) );
$data .= '<div class="rank-math-business-wrapper">';
$data .= $this->get_title( $schema );
$data .= $this->get_image( $schema );
if ( 'address' === $this->atts['type'] ) {
$data .= $this->address->get_data( $this, $schema );
}
if ( 'opening-hours' === $this->atts['type'] || $this->atts['show_opening_hours'] ) {
$data .= $this->opening_hours->get_data( $this, $schema );
}
$data .= '</div>';
}
return $data;
}
/**
* Get Location Title.
*
* @param Object $schema Location schema data.
*
* @return string Shortcode data.
*/
public function get_title( $schema ) {
if ( empty( $this->atts['show_company_name'] ) || empty( $schema['name'] ) ) {
return;
}
return '<h3 class="rank-math-business-name">' . esc_html( $schema['name'] ) . '</h3>';
}
/**
* Get Location Image.
*
* @param Object $schema Schema Data.
*
* @return string Shortcode data.
*/
public function get_image( $schema ) {
if ( empty( $this->atts['show_logo'] ) || empty( $schema['image'] ) ) {
return;
}
return '<div class="rank-math-business-image"><img src="' . esc_url( $schema['image']['url'] ) . '" /><div>';
}
/**
* Replace variable.
*
* @param array $schemas Schema to replace.
* @param object $location Location Post Object.
* @return array
*/
public function replace_variables( $schemas, $location = [] ) {
$new_schemas = [];
foreach ( $schemas as $key => $schema ) {
if ( is_array( $schema ) ) {
$new_schemas[ $key ] = $this->replace_variables( $schema, $location );
continue;
}
$new_schemas[ $key ] = Str::contains( '%', $schema ) ? Helper::replace_seo_fields( $schema, $location ) : $schema;
}
return $new_schemas;
}
/**
* Shortcode & Block default attributes.
*/
private function get_attributes() {
return [
'type' => [
'default' => 'address',
'type' => 'string',
],
'locations' => [
'default' => '',
'type' => 'string',
],
'terms' => [
'default' => [],
'type' => 'array',
],
'limit' => [
'default' => Helper::get_settings( 'titles.limit_results', 10 ),
'type' => 'integer',
],
'show_company_name' => [
'type' => 'boolean',
'default' => true,
],
'show_company_address' => [
'type' => 'boolean',
'default' => true,
],
'show_on_one_line' => [
'type' => 'boolean',
'default' => false,
],
'show_state' => [
'type' => 'boolean',
'default' => true,
],
'show_country' => [
'type' => 'boolean',
'default' => true,
],
'show_telephone' => [
'type' => 'boolean',
'default' => true,
],
'show_secondary_number' => [
'type' => 'boolean',
'default' => true,
],
'show_fax' => [
'type' => 'boolean',
'default' => false,
],
'show_email' => [
'type' => 'boolean',
'default' => true,
],
'show_url' => [
'type' => 'boolean',
'default' => true,
],
'show_logo' => [
'type' => 'boolean',
'default' => true,
],
'show_vat_id' => [
'type' => 'boolean',
'default' => false,
],
'show_tax_id' => [
'type' => 'boolean',
'default' => false,
],
'show_coc_id' => [
'type' => 'boolean',
'default' => false,
],
'show_priceRange' => [
'type' => 'boolean',
'default' => false,
],
'show_opening_hours' => [
'type' => 'boolean',
'default' => false,
],
'show_days' => [
'type' => 'string',
'default' => 'Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday',
],
'hide_closed_days' => [
'type' => 'boolean',
'default' => false,
],
'show_opening_now_label' => [
'type' => 'boolean',
'default' => false,
],
'opening_hours_note' => [
'type' => 'string',
'default' => 'Open Now',
],
'show_map' => [
'type' => 'boolean',
'default' => false,
],
'map_style' => [
'type' => 'string',
'default' => Helper::get_settings( 'titles.map_style', 'roadmap' ),
],
'map_width' => [
'type' => 'string',
'default' => '100%',
],
'map_height' => [
'type' => 'string',
'default' => '300px',
],
'zoom_level' => [
'type' => 'integer',
'default' => -1,
],
'allow_zoom' => [
'type' => 'boolean',
'default' => true,
],
'allow_scrolling' => [
'type' => 'boolean',
'default' => true,
],
'allow_dragging' => [
'type' => 'boolean',
'default' => true,
],
'show_route_planner' => [
'type' => 'boolean',
'default' => true,
],
'route_label' => [
'type' => 'string',
'default' => Helper::get_settings( 'titles.route_label' ),
],
'show_category_filter' => [
'type' => 'boolean',
'default' => false,
],
'show_marker_clustering' => [
'type' => 'boolean',
'default' => true,
],
'show_infowindow' => [
'type' => 'boolean',
'default' => true,
],
'show_radius' => [
'type' => 'boolean',
'default' => true,
],
'show_nearest_location' => [
'type' => 'boolean',
'default' => true,
],
'search_radius' => [
'type' => 'string',
'default' => '10',
],
];
}
}

View File

@@ -0,0 +1,68 @@
<?php
/**
* The Rank Math Tutorial class.
*
* @since 2.1.2
* @package RankMath
* @subpackage RankMathPro
* @author Rank Math <support@rankmath.com>
*
* @copyright Copyright (C) 2008-2020, WooCommerce
* The following code is a derivative work of the code from the WooCommerce(https://github.com/woocommerce/woocommerce), which is licensed under GPL v3.
*/
namespace RankMathPro\Local_Seo;
use RankMath\Traits\Hooker;
use MyThemeShop\Helpers\Param;
defined( 'ABSPATH' ) || exit;
/**
* RM_Pointers Class.
*/
class RM_Pointers {
use Hooker;
/**
* Constructor.
*/
public function __construct() {
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
$this->action( 'admin_enqueue_scripts', 'enqueue_pointers' );
}
/**
* Enqueue pointers and add script to page.
*/
public function enqueue_pointers() {
$screen = get_current_screen();
if ( ! $screen || 'rank_math_locations' !== $screen->id ) {
return;
}
if ( get_option( 'rank_math_remove_locations_tutorial' ) ) {
return;
}
update_option( 'rank_math_remove_locations_tutorial', true );
wp_enqueue_style( 'wp-pointer' );
wp_enqueue_script(
'rank-math-pro-pointers',
RANK_MATH_PRO_URL . 'includes/modules/local-seo/assets/js/rank-math-pointers.js',
[
'jquery',
'wp-pointer',
'wp-i18n',
'lodash',
],
rank_math_pro()->version,
true
);
}
}

View File

@@ -0,0 +1,60 @@
<?php
/**
* The Local_Seo Module
*
* @since 1.0.0
* @package RankMathPro
* @subpackage RankMath
* @author Rank Math <support@rankmath.com>
*/
namespace RankMathPro\Local_Seo;
use RankMath\Helper;
use RankMath\Traits\Hooker;
defined( 'ABSPATH' ) || exit;
/**
* Search class.
*/
class Search {
use Hooker;
/**
* The Constructor.
*/
public function __construct() {
$this->action( 'wp', 'integrations' );
}
/**
* Initialize integrations.
*/
public function integrations() {
if ( ! is_search() || ! Helper::get_settings( 'titles.locations_enhanced_search' ) ) {
return;
}
$this->filter( 'the_excerpt', 'add_locations_data' );
}
/**
* Add Locations data to search results.
*
* @param string $excerpt Post excerpt.
* @return string $excerpt Processed excerpt.
*/
public function add_locations_data( $excerpt ) {
global $post;
if ( get_post_type( $post->ID ) !== 'rank_math_locations' ) {
return $excerpt;
}
$excerpt .= do_shortcode( '[rank_math_local type="address" locations="' . $post->ID . '" show_company_name=""]' );
return $excerpt;
}
}

View File

@@ -0,0 +1,122 @@
<?php
/**
* The Address shortcode Class.
*
* @since 1.0.1
* @package RankMath
* @subpackage RankMathPro
* @author Rank Math <support@rankmath.com>
*/
namespace RankMathPro\Local_Seo;
use RankMath\Helper;
defined( 'ABSPATH' ) || exit;
/**
* Address class.
*/
class Address {
/**
* Get Address Data.
*
* @param Location_Shortcode $shortcode Location_Shortcode Instance.
* @param array $schema Array of Schema data.
*
* @return string
*/
public function get_data( $shortcode, $schema ) {
$atts = $shortcode->atts;
$data = $this->get_address( $schema, $atts );
$schema = $schema['metadata'] + $schema;
$labels = [
'telephone' => [
'key' => 'telephone',
'label' => esc_html__( 'Phone', 'rank-math-pro' ),
],
'secondary_number' => [
'key' => 'secondary_number',
'label' => esc_html__( 'Secondary phone', 'rank-math-pro' ),
],
'fax' => [
'key' => 'faxNumber',
'label' => esc_html__( 'Fax', 'rank-math-pro' ),
],
'email' => [
'key' => 'email',
'label' => esc_html__( 'Email', 'rank-math-pro' ),
],
'url' => [
'key' => 'url',
'label' => esc_html__( 'URL', 'rank-math-pro' ),
],
'vat_id' => [
'key' => 'vatID',
'label' => esc_html__( 'VAT ID', 'rank-math-pro' ),
],
'tax_id' => [
'key' => 'taxID',
'label' => esc_html__( 'Tax ID', 'rank-math-pro' ),
],
'coc_id' => [
'key' => 'coc_id',
'label' => esc_html__( 'Chamber of Commerce ID', 'rank-math-pro' ),
],
'priceRange' => [
'key' => 'priceRange',
'label' => esc_html__( 'Price indication', 'rank-math-pro' ),
],
];
foreach ( $labels as $key => $label ) {
if ( empty( $atts[ "show_$key" ] ) || empty( $schema[ $label['key'] ] ) ) {
continue;
}
$value = esc_html( $schema[ $label['key'] ] );
if ( 'email' === $key ) {
$value = '<a href="mailto:' . $value . '">' . $value . '</a>';
}
if ( in_array( $key, [ 'telephone', 'secondary_number' ], true ) ) {
$value = '<a href="tel:' . $value . '">' . $value . '</a>';
}
$data .= '<div><strong>' . $label['label'] . '</strong>: ' . $value . '</div>';
}
return $data;
}
/**
* Get Address Data.
*
* @param array $schema Array of Schema data.
* @param array $atts Shortcode attributes.
*
* @return string
*/
public function get_address( $schema, $atts = [] ) {
$address = array_filter( $schema['address'] );
if ( false === $address || empty( $atts['show_company_address'] ) ) {
return '';
}
$hash = array_filter(
[
'streetAddress' => true,
'addressLocality' => true,
'addressRegion' => ! empty( $atts['show_state'] ),
'addressCountry' => ! empty( $atts['show_country'] ),
'postalCode' => true,
]
);
$glue = empty( $atts['show_on_one_line'] ) ? ',<br />' : ', ';
$data = implode( $glue, array_intersect_key( $address, $hash ) );
return '<h5>' . esc_html__( 'Address:', 'rank-math-pro' ) . '</h5><address>' . $data . '</address>';
}
}

View File

@@ -0,0 +1,119 @@
<?php
/**
* The Map shortcode Class.
*
* @since 1.0.1
* @package RankMath
* @subpackage RankMathPro
* @author Rank Math <support@rankmath.com>
*/
namespace RankMathPro\Local_Seo;
use RankMath\Schema\DB;
defined( 'ABSPATH' ) || exit;
/**
* Map class.
*/
class Map {
/**
* Shortcode Instance.
*
* @var Location_Shortcode
*/
public $shortcode;
/**
* Get Address Data.
*
* @param Location_Shortcode $shortcode Location_Shortcode Instance.
* @param array $locations Locations data.
* @return string
*/
public function get_data( $shortcode, $locations ) {
$this->shortcode = $shortcode;
$atts = $shortcode->atts;
$options = [
'map_style' => $atts['map_style'],
'allow_zoom' => $atts['allow_zoom'],
'zoom_level' => $atts['zoom_level'],
'allow_dragging' => $atts['allow_dragging'],
'show_clustering' => $atts['show_marker_clustering'],
'show_infowindow' => $atts['show_infowindow'],
];
$terms_data = [];
foreach ( $locations as $location ) {
$schema = DB::get_schemas( $location->ID );
if ( empty( $schema ) ) {
continue;
}
$schema = current( $shortcode->replace_variables( $schema ) );
if ( empty( $schema['geo']['latitude'] ) || empty( $schema['geo']['longitude'] ) ) {
continue;
}
$options['locations'][ $location->ID ] = [
'content' => $this->get_infobox_content( $location->ID, $schema ),
'lat' => $schema['geo']['latitude'],
'lng' => $schema['geo']['longitude'],
];
if ( ! empty( $atts['show_category_filter'] ) && 'map' === $atts['type'] ) {
$terms = get_the_terms( $location->ID, 'rank_math_location_category' );
if ( ! is_wp_error( $terms ) && ! empty( $terms ) ) {
$terms_data = array_merge( $terms_data, $terms );
$options['locations'][ $location->ID ]['terms'] = wp_list_pluck( $terms, 'term_id' );
}
}
}
if ( empty( $options['locations'] ) ) {
return;
}
wp_enqueue_script( 'rank-math-local' );
$width = ! empty( $atts['map_width'] ) ? $atts['map_width'] : '100%';
$height = ! empty( $atts['map_height'] ) ? $atts['map_height'] : '500px';
$style = sprintf( 'style="width: %s; height: %s"', $width, $height );
ob_start();
?>
<div class="rank-math-local-map-wrapper">
<div class="rank-math-local-map" data-map-options="<?php echo esc_attr( wp_json_encode( $options ) ); ?>" <?php printf( 'style="width: %s; height: %s"', esc_attr( $width ), esc_attr( $height ) ); ?>></div>
<?php
if ( ! empty( $terms_data ) ) {
echo '<select id="rank-math-select-category">';
echo '<option value="">' . esc_html__( 'Select Category', 'rank-math-pro' ) . '</option>';
foreach ( $terms_data as $term ) {
echo '<option value="' . esc_attr( $term->term_id ) . '">' . esc_html( $term->name ) . '</option>';
}
echo '</select>';
}
?>
</div>
<?php
return ob_get_clean();
}
/**
* Get Infobox Content.
*
* @param int $location_id The Location ID.
* @param array $schema Schema Data.
* @return string
*/
public function get_infobox_content( $location_id, $schema ) {
return '<div class="rank-math-infobox-wrapper">
<h5><a href="' . esc_url( get_the_permalink( $location_id ) ) . '">' . esc_html( get_the_title( $location_id ) ) . '</a></h5>
<p>' . $this->shortcode->address->get_data( $this->shortcode, $schema ) . '</p>
</div>';
}
}

View File

@@ -0,0 +1,158 @@
<?php
/**
* The Opening Hours shortcode Class.
*
* @since 1.0.1
* @package RankMath
* @subpackage RankMathPro
* @author Rank Math <support@rankmath.com>
*/
namespace RankMathPro\Local_Seo;
use RankMath\Helper;
defined( 'ABSPATH' ) || exit;
/**
* Opening_Hours class.
*/
class Opening_Hours {
/**
* Get Opening_Hours Data.
*
* @param Location_Shortcode $shortcode Location_Shortcode Instance.
* @param array $schema Schema data.
* @return string
*/
public function get_data( $shortcode, $schema ) {
if ( ! isset( $schema['openingHoursSpecification'] ) ) {
return '<p>' . esc_html__( 'Open 24/7', 'rank-math-pro' ) . '</p>';
}
if ( empty( $schema['openingHoursSpecification'] ) ) {
return false;
}
$days = $this->normalize_days( $schema, $shortcode );
ob_start();
?>
<h5><?php esc_html_e( 'Opening Hours:', 'rank-math-pro' ); ?></h5>
<div class="rank-math-business-opening-hours">
<?php
foreach ( $days as $day => $hours ) {
$time = ! empty( $hours['time'] ) ? implode( ' and ', $hours['time'] ) : esc_html__( 'Closed', 'rank-math-pro' );
$time = str_replace( '-', ' &ndash; ', $time );
printf(
'<div class="rank-math-opening-hours"><span class="rank-math-opening-days">%1$s</span> : <span class="rank-math-opening-time">%2$s</span> <span class="rank-math-business-open">%3$s</span></div>',
esc_html( $this->get_localized_day( $day ) ),
esc_html( $time ),
esc_html( $hours['isOpen'] )
);
}
?>
</div>
<?php
return ob_get_clean();
}
/**
* Get Local Time.
*
* @param Location_Shortcode $shortcode Location_Shortcode Instance.
* @param array $schema Schema data.
* @return string
*/
private function get_local_time( $shortcode, $schema ) {
if ( empty( $shortcode->atts['show_opening_now_label'] ) ) {
return false;
}
$timezone = ! empty( $schema['metadata']['timeZone'] ) ? $schema['metadata']['timeZone'] : wp_timezone_string();
$local_datetime = new \DateTime( 'now', new \DateTimeZone( $timezone ) );
return [
'day' => $local_datetime->format( 'l' ),
'time' => strtotime( $local_datetime->format( 'H:i' ) ),
];
}
/**
* Normalize Weekdays.
*
* @param array $schema Schema data.
* @param Location_Shortcode $shortcode Location_Shortcode Instance.
* @return array
*/
private function normalize_days( $schema, $shortcode ) {
$hours = $schema['openingHoursSpecification'];
$days = explode( ',', $shortcode->atts['show_days'] );
$format = ! isset( $schema['metadata']['use_24h_format'] ) ? Helper::get_settings( 'titles.opening_hours_format' ) : empty( $schema['metadata']['use_24h_format'] );
$data = [];
$local_time = $this->get_local_time( $shortcode, $schema );
foreach ( $days as $day ) {
$day = ucfirst( trim( $day ) );
$data[ $day ] = [
'isOpen' => '',
];
foreach ( $hours as $hour ) {
if ( ! in_array( $day, (array) $hour['dayOfWeek'], true ) ) {
continue;
}
$open = strtotime( $hour['opens'] );
$close = strtotime( $hour['closes'] );
$is_open = ! empty( $local_time ) &&
$day === $local_time['day'] &&
$local_time['time'] >= $open &&
$local_time['time'] <= $close;
$data[ $day ]['time'][] = $format ? date_i18n( 'g:i a', $open ) . ' - ' . date_i18n( 'g:i a', $close ) : $hour['opens'] . ' - ' . $hour['closes'];
$data[ $day ]['isOpen'] = $is_open ? $this->get_opening_hours_note( $shortcode ) : '';
}
if ( $shortcode->atts['hide_closed_days'] && empty( $data[ $day ]['time'] ) ) {
unset( $data[ $day ] );
}
}
return $data;
}
/**
* Get Opening Hours note.
*
* @param Location_Shortcode $shortcode Location_Shortcode Instance.
* @return string
*/
private function get_opening_hours_note( $shortcode ) {
return empty( $shortcode->atts['opening_hours_note'] ) ? esc_html__( 'Open now', 'rank-math-pro' ) : esc_html( $shortcode->atts['opening_hours_note'] );
}
/**
* Retrieve the full translated weekday word.
*
* @param string $day Day to translate.
*
* @return string
*/
private function get_localized_day( $day ) {
global $wp_locale;
$hash = [
'Sunday' => 0,
'Monday' => 1,
'Tuesday' => 2,
'Wednesday' => 3,
'Thursday' => 4,
'Friday' => 5,
'Saturday' => 6,
];
return ! isset( $hash[ $day ] ) ? $day : $wp_locale->get_weekday( $hash[ $day ] );
}
}

View File

@@ -0,0 +1,232 @@
<?php
/**
* The Store Locator shortcode Class.
*
* @since 1.0.1
* @package RankMath
* @subpackage RankMathPro
* @author Rank Math <support@rankmath.com>
*/
namespace RankMathPro\Local_Seo;
use RankMath\Helper;
use RankMath\Post;
use RankMath\Schema\DB;
use MyThemeShop\Helpers\Param;
defined( 'ABSPATH' ) || exit;
/**
* Store_Locator class.
*/
class Store_Locator {
/**
* Get Store_Locator Data.
*
* @param Location_Shortcode $shortcode Location_Shortcode Instance.
* @return string
*/
public function get_data( $shortcode ) {
$unit = 'miles' === Helper::get_settings( 'titles.map_unit', 'kilometers' ) ? 'mi' : 'km';
$radius = Param::post( 'rank-math-search-radius', 20 );
$address = Param::post( 'rank-math-search-address' );
$category = Param::post( 'rank-math-location-category' );
$terms = empty( $shortcode->atts['show_category_filter'] )
? []
: get_terms(
[
'taxonomy' => 'rank_math_location_category',
'fields' => 'id=>name',
]
);
wp_enqueue_script( 'rank-math-local' );
ob_start();
?>
<div class="rank-math-business-wrapper">
<form id="rank-math-local-store-locator" method="post" action="#rank-math-local-store-locator">
<?php if ( ! empty( $shortcode->atts['show_radius'] ) ) { ?>
<div class="rank-math-form-field">
<select name="rank-math-search-radius">
<?php
foreach ( [ 1, 5, 10, 20, 40, 50, 75, 100, 200, 300, 400, 500, 1000 ] as $value ) {
echo "<option value='{$value}' " . selected( $radius, $value, true ) . ">{$value}{$unit}</option>";
}
?>
</select>
</div>
<?php } ?>
<?php if ( ! empty( $terms ) ) { ?>
<div class="rank-math-form-field">
<select name="rank-math-location-category">
<option value=""><?php echo esc_html__( 'Select Category', 'rank-math-pro' ); ?></option>
<?php foreach ( $terms as $term_id => $term_name ) { ?>
<option value="<?php echo esc_attr( $term_id ); ?>" <?php selected( $category, $term_id ); ?>><?php echo esc_html( $term_name ); ?></option>
<?php } ?>
</select>
</div>
<?php } ?>
<div class="rank-math-form-field">
<input type="text" name="rank-math-search-address" id="rank-math-search-address" placeholder="<?php echo esc_html__( 'Address, Suburb, Region, Zip or Landmark', 'rank-math-pro' ); ?>" value="<?php echo esc_attr( $address ); ?>" />
<input type="hidden" name="lat" id="rank-math-lat" />
<input type="hidden" name="lng" id="rank-math-lng" />
</div>
<?php $this->detect_location(); ?>
<div class="rank-math-form-field">
<button type="submit" name="rank-math-submit" value="search"><?php echo esc_html__( 'Search', 'rank-math-pro' ); ?></button>
</div>
</form>
<?php
echo $this->get_results( $shortcode, $unit );
echo '</div>';
return ob_get_clean();
}
/**
* Add detect current location button.
*
* @return string
*/
private function detect_location() {
if ( ! Helper::get_settings( 'titles.enable_location_detection' ) ) {
return;
}
echo '<a href="#" id="rank-math-current-location">' . esc_html__( 'Detect Location', 'rank-math-pro' ) . '</a>';
}
/**
* Get Map Results.
*
* @param Location_Shortcode $shortcode Location_Shortcode Instance.
* @param string $unit Map measurement unit.
* @return string
*/
private function get_results( $shortcode, $unit ) {
if ( ! Param::post( 'rank-math-search-address' ) ) {
return false;
}
global $wpdb;
// Radius of the earth 3959 miles or 6371 kilometers.
$earth_radius = 'mi' === $unit ? 3959 : 6371;
$radius = ! empty( $shortcode->atts['show_radius'] ) ? Param::post( 'rank-math-search-radius', 20 ) : $shortcode->atts['search_radius'];
$latitude = Param::post( 'lat' );
$longitude = Param::post( 'lng' );
$category = Param::post( 'rank-math-location-category', 0, FILTER_VALIDATE_INT );
$inner_join = '';
if ( $category ) {
$inner_join .= $wpdb->prepare(
"INNER JOIN $wpdb->term_relationships AS tr ON p.ID = tr.object_id
INNER JOIN $wpdb->term_taxonomy AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
AND tt.taxonomy = 'rank_math_location_category'
AND tt.term_id = %d",
$category
);
}
$nearby_locations = $wpdb->get_results(
$wpdb->prepare(
"SELECT DISTINCT
p.*,
map_lat.meta_value as locLat,
map_lng.meta_value as locLong,
( %d * acos(
cos( radians( %s ) )
* cos( radians( map_lat.meta_value ) )
* cos( radians( map_lng.meta_value ) - radians( %s ) )
+ sin( radians( %s ) )
* sin( radians( map_lat.meta_value ) )
) )
AS distance
FROM $wpdb->posts p
INNER JOIN $wpdb->postmeta map_lat ON p.ID = map_lat.post_id
INNER JOIN $wpdb->postmeta map_lng ON p.ID = map_lng.post_id
$inner_join
WHERE 1 = 1
AND p.post_type = 'rank_math_locations'
AND p.post_status = 'publish'
AND map_lat.meta_key = 'rank_math_local_business_latitide'
AND map_lng.meta_key = 'rank_math_local_business_longitude'
HAVING distance < %s
ORDER BY distance ASC",
$earth_radius,
$latitude,
$longitude,
$latitude,
$radius
)
);
//phpcs:enable
if ( empty( $nearby_locations ) ) {
return esc_html__( 'Sorry, no locations were found.', 'rank-math-pro' );
}
$data = ! empty( $shortcode->atts['show_map'] ) ? $shortcode->map->get_data( $shortcode, $nearby_locations ) : '';
foreach ( $nearby_locations as $location ) {
$schema = DB::get_schemas( $location->ID );
if ( empty( $schema ) ) {
continue;
}
$schema = current( $shortcode->replace_variables( $schema, $location ) );
$data .= $shortcode->get_title( $schema );
$data .= $shortcode->address->get_data( $shortcode, $schema );
$data .= ! empty( $shortcode->atts['show_opening_hours'] ) ? $shortcode->opening_hours->get_data( $shortcode, $schema ) : '';
$data .= $this->get_directions( $location, $shortcode );
}
return $data;
}
/**
* Get Map Results.
*
* @param Object $location Current Location Post.
* @param Location_Shortcode $shortcode Location_Shortcode Instance.
* @return string
*/
public function get_directions( $location, $shortcode ) {
if ( empty( $shortcode->atts['show_route_planner'] ) || empty( $shortcode->atts['show_map'] ) ) {
return '';
}
$lat = Post::get_meta( 'local_business_latitide', $location->ID );
$lng = Post::get_meta( 'local_business_longitude', $location->ID );
ob_start();
?>
<div class="rank-math-directions-wrapper">
<a href="#" class="rank-math-show-route" data-toggle-text="<?php echo esc_html__( 'Hide route', 'rank-math-pro' ); ?>">
<?php echo esc_html( $shortcode->atts['route_label'] ); ?>
</a>
<div class="rank-math-directions-result">
<h3><?php echo esc_html__( 'Route', 'rank-math-pro' ); ?></h3>
<div class="rank-math-directions-form">
<form method="post">
<div class="rank-math-form-field">
<label for="origin"><?php echo esc_html__( 'Your location:', 'rank-math-pro' ); ?></label>
<input type="text" name="origin" id="rank-math-origin" value="<?php echo esc_attr( Param::post( 'rank-math-search-address' ) ); ?>" />
<input type="submit" name="get-direction" value="<?php echo esc_html__( 'Show route', 'rank-math-pro' ); ?>" />
<input type="hidden" name="rank-math-lat" id="rank-math-lat" value="<?php echo esc_attr( $lat ); ?>" />
<input type="hidden" name="rank-math-lng" id="rank-math-lng" value="<?php echo esc_attr( $lng ); ?>" />
</div>
</form>
</div>
<div class="rank-math-directions"></div>
</div>
</div>
<?php
return ob_get_clean();
}
}

View File

@@ -0,0 +1,21 @@
<?php
/**
* Locations KML File settings.
*
* @since 2.2.0
* @package RankMath
* @subpackage RankMathPro
* @author MyThemeShop <admin@mythemeshop.com>
*/
defined( 'ABSPATH' ) || exit;
$cmb->add_field(
[
'id' => 'local_sitemap',
'type' => 'toggle',
'name' => esc_html__( 'Include KML File in the Sitemap', 'rank-math-pro' ),
'desc' => esc_html__( 'locations.kml Sitemap is generated automatically when the Local SEO module is enabled, and the geo-coordinates are added.', 'rank-math-pro' ),
'default' => 'on',
]
);

View File

@@ -0,0 +1,764 @@
<?php
/**
* The local seo settings.
*
* @package RankMath
* @subpackage RankMathPro
*/
use RankMath\Helper;
defined( 'ABSPATH' ) || exit;
$company = [ [ 'knowledgegraph_type', 'company' ] ];
$person = [ [ 'knowledgegraph_type', 'person' ] ];
$use_multiple_locations = [ 'relation' => 'and' ] + $company;
$use_multiple_locations[] = [ 'use_multiple_locations', 'on' ];
$hide_on_multiple_locations = [ 'relation' => 'and' ] + $company;
$hide_on_multiple_locations[] = [ 'use_multiple_locations', 'on', '!=' ];
$countries = [
'' => __( 'Choose a country', 'rank-math-pro' ),
'AX' => __( 'Åland Islands', 'rank-math-pro' ),
'AF' => __( 'Afghanistan', 'rank-math-pro' ),
'AL' => __( 'Albania', 'rank-math-pro' ),
'DZ' => __( 'Algeria', 'rank-math-pro' ),
'AD' => __( 'Andorra', 'rank-math-pro' ),
'AO' => __( 'Angola', 'rank-math-pro' ),
'AI' => __( 'Anguilla', 'rank-math-pro' ),
'AQ' => __( 'Antarctica', 'rank-math-pro' ),
'AG' => __( 'Antigua and Barbuda', 'rank-math-pro' ),
'AR' => __( 'Argentina', 'rank-math-pro' ),
'AM' => __( 'Armenia', 'rank-math-pro' ),
'AW' => __( 'Aruba', 'rank-math-pro' ),
'AU' => __( 'Australia', 'rank-math-pro' ),
'AT' => __( 'Austria', 'rank-math-pro' ),
'AZ' => __( 'Azerbaijan', 'rank-math-pro' ),
'BS' => __( 'Bahamas', 'rank-math-pro' ),
'BH' => __( 'Bahrain', 'rank-math-pro' ),
'BD' => __( 'Bangladesh', 'rank-math-pro' ),
'BB' => __( 'Barbados', 'rank-math-pro' ),
'BY' => __( 'Belarus', 'rank-math-pro' ),
'PW' => __( 'Belau', 'rank-math-pro' ),
'BE' => __( 'Belgium', 'rank-math-pro' ),
'BZ' => __( 'Belize', 'rank-math-pro' ),
'BJ' => __( 'Benin', 'rank-math-pro' ),
'BM' => __( 'Bermuda', 'rank-math-pro' ),
'BT' => __( 'Bhutan', 'rank-math-pro' ),
'BO' => __( 'Bolivia', 'rank-math-pro' ),
'BQ' => __( 'Bonaire, Sint Eustatius and Saba', 'rank-math-pro' ),
'BA' => __( 'Bosnia and Herzegovina', 'rank-math-pro' ),
'BW' => __( 'Botswana', 'rank-math-pro' ),
'BV' => __( 'Bouvet Island', 'rank-math-pro' ),
'BR' => __( 'Brazil', 'rank-math-pro' ),
'IO' => __( 'British Indian Ocean Territory', 'rank-math-pro' ),
'VG' => __( 'British Virgin Islands', 'rank-math-pro' ),
'BN' => __( 'Brunei', 'rank-math-pro' ),
'BG' => __( 'Bulgaria', 'rank-math-pro' ),
'BF' => __( 'Burkina Faso', 'rank-math-pro' ),
'BI' => __( 'Burundi', 'rank-math-pro' ),
'KH' => __( 'Cambodia', 'rank-math-pro' ),
'CM' => __( 'Cameroon', 'rank-math-pro' ),
'CA' => __( 'Canada', 'rank-math-pro' ),
'CV' => __( 'Cape Verde', 'rank-math-pro' ),
'KY' => __( 'Cayman Islands', 'rank-math-pro' ),
'CF' => __( 'Central African Republic', 'rank-math-pro' ),
'TD' => __( 'Chad', 'rank-math-pro' ),
'CL' => __( 'Chile', 'rank-math-pro' ),
'CN' => __( 'China', 'rank-math-pro' ),
'CX' => __( 'Christmas Island', 'rank-math-pro' ),
'CC' => __( 'Cocos (Keeling) Islands', 'rank-math-pro' ),
'CO' => __( 'Colombia', 'rank-math-pro' ),
'KM' => __( 'Comoros', 'rank-math-pro' ),
'CG' => __( 'Congo (Brazzaville)', 'rank-math-pro' ),
'CD' => __( 'Congo (Kinshasa)', 'rank-math-pro' ),
'CK' => __( 'Cook Islands', 'rank-math-pro' ),
'CR' => __( 'Costa Rica', 'rank-math-pro' ),
'HR' => __( 'Croatia', 'rank-math-pro' ),
'CU' => __( 'Cuba', 'rank-math-pro' ),
'CW' => __( 'Curaçao', 'rank-math-pro' ),
'CY' => __( 'Cyprus', 'rank-math-pro' ),
'CZ' => __( 'Czech Republic', 'rank-math-pro' ),
'DK' => __( 'Denmark', 'rank-math-pro' ),
'DJ' => __( 'Djibouti', 'rank-math-pro' ),
'DM' => __( 'Dominica', 'rank-math-pro' ),
'DO' => __( 'Dominican Republic', 'rank-math-pro' ),
'EC' => __( 'Ecuador', 'rank-math-pro' ),
'EG' => __( 'Egypt', 'rank-math-pro' ),
'SV' => __( 'El Salvador', 'rank-math-pro' ),
'GQ' => __( 'Equatorial Guinea', 'rank-math-pro' ),
'ER' => __( 'Eritrea', 'rank-math-pro' ),
'EE' => __( 'Estonia', 'rank-math-pro' ),
'ET' => __( 'Ethiopia', 'rank-math-pro' ),
'FK' => __( 'Falkland Islands', 'rank-math-pro' ),
'FO' => __( 'Faroe Islands', 'rank-math-pro' ),
'FJ' => __( 'Fiji', 'rank-math-pro' ),
'FI' => __( 'Finland', 'rank-math-pro' ),
'FR' => __( 'France', 'rank-math-pro' ),
'GF' => __( 'French Guiana', 'rank-math-pro' ),
'PF' => __( 'French Polynesia', 'rank-math-pro' ),
'TF' => __( 'French Southern Territories', 'rank-math-pro' ),
'GA' => __( 'Gabon', 'rank-math-pro' ),
'GM' => __( 'Gambia', 'rank-math-pro' ),
'GE' => __( 'Georgia', 'rank-math-pro' ),
'DE' => __( 'Germany', 'rank-math-pro' ),
'GH' => __( 'Ghana', 'rank-math-pro' ),
'GI' => __( 'Gibraltar', 'rank-math-pro' ),
'GR' => __( 'Greece', 'rank-math-pro' ),
'GL' => __( 'Greenland', 'rank-math-pro' ),
'GD' => __( 'Grenada', 'rank-math-pro' ),
'GP' => __( 'Guadeloupe', 'rank-math-pro' ),
'GT' => __( 'Guatemala', 'rank-math-pro' ),
'GG' => __( 'Guernsey', 'rank-math-pro' ),
'GN' => __( 'Guinea', 'rank-math-pro' ),
'GW' => __( 'Guinea-Bissau', 'rank-math-pro' ),
'GY' => __( 'Guyana', 'rank-math-pro' ),
'HT' => __( 'Haiti', 'rank-math-pro' ),
'HM' => __( 'Heard Island and McDonald Islands', 'rank-math-pro' ),
'HN' => __( 'Honduras', 'rank-math-pro' ),
'HK' => __( 'Hong Kong', 'rank-math-pro' ),
'HU' => __( 'Hungary', 'rank-math-pro' ),
'IS' => __( 'Iceland', 'rank-math-pro' ),
'IN' => __( 'India', 'rank-math-pro' ),
'ID' => __( 'Indonesia', 'rank-math-pro' ),
'IR' => __( 'Iran', 'rank-math-pro' ),
'IQ' => __( 'Iraq', 'rank-math-pro' ),
'IM' => __( 'Isle of Man', 'rank-math-pro' ),
'IL' => __( 'Israel', 'rank-math-pro' ),
'IT' => __( 'Italy', 'rank-math-pro' ),
'CI' => __( 'Ivory Coast', 'rank-math-pro' ),
'JM' => __( 'Jamaica', 'rank-math-pro' ),
'JP' => __( 'Japan', 'rank-math-pro' ),
'JE' => __( 'Jersey', 'rank-math-pro' ),
'JO' => __( 'Jordan', 'rank-math-pro' ),
'KZ' => __( 'Kazakhstan', 'rank-math-pro' ),
'KE' => __( 'Kenya', 'rank-math-pro' ),
'KI' => __( 'Kiribati', 'rank-math-pro' ),
'KW' => __( 'Kuwait', 'rank-math-pro' ),
'KG' => __( 'Kyrgyzstan', 'rank-math-pro' ),
'LA' => __( 'Laos', 'rank-math-pro' ),
'LV' => __( 'Latvia', 'rank-math-pro' ),
'LB' => __( 'Lebanon', 'rank-math-pro' ),
'LS' => __( 'Lesotho', 'rank-math-pro' ),
'LR' => __( 'Liberia', 'rank-math-pro' ),
'LY' => __( 'Libya', 'rank-math-pro' ),
'LI' => __( 'Liechtenstein', 'rank-math-pro' ),
'LT' => __( 'Lithuania', 'rank-math-pro' ),
'LU' => __( 'Luxembourg', 'rank-math-pro' ),
'MO' => __( 'Macao S.A.R., China', 'rank-math-pro' ),
'MK' => __( 'Macedonia', 'rank-math-pro' ),
'MG' => __( 'Madagascar', 'rank-math-pro' ),
'MW' => __( 'Malawi', 'rank-math-pro' ),
'MY' => __( 'Malaysia', 'rank-math-pro' ),
'MV' => __( 'Maldives', 'rank-math-pro' ),
'ML' => __( 'Mali', 'rank-math-pro' ),
'MT' => __( 'Malta', 'rank-math-pro' ),
'MH' => __( 'Marshall Islands', 'rank-math-pro' ),
'MQ' => __( 'Martinique', 'rank-math-pro' ),
'MR' => __( 'Mauritania', 'rank-math-pro' ),
'MU' => __( 'Mauritius', 'rank-math-pro' ),
'YT' => __( 'Mayotte', 'rank-math-pro' ),
'MX' => __( 'Mexico', 'rank-math-pro' ),
'FM' => __( 'Micronesia', 'rank-math-pro' ),
'MD' => __( 'Moldova', 'rank-math-pro' ),
'MC' => __( 'Monaco', 'rank-math-pro' ),
'MN' => __( 'Mongolia', 'rank-math-pro' ),
'ME' => __( 'Montenegro', 'rank-math-pro' ),
'MS' => __( 'Montserrat', 'rank-math-pro' ),
'MA' => __( 'Morocco', 'rank-math-pro' ),
'MZ' => __( 'Mozambique', 'rank-math-pro' ),
'MM' => __( 'Myanmar', 'rank-math-pro' ),
'NA' => __( 'Namibia', 'rank-math-pro' ),
'NR' => __( 'Nauru', 'rank-math-pro' ),
'NP' => __( 'Nepal', 'rank-math-pro' ),
'NL' => __( 'Netherlands', 'rank-math-pro' ),
'AN' => __( 'Netherlands Antilles', 'rank-math-pro' ),
'NC' => __( 'New Caledonia', 'rank-math-pro' ),
'NZ' => __( 'New Zealand', 'rank-math-pro' ),
'NI' => __( 'Nicaragua', 'rank-math-pro' ),
'NE' => __( 'Niger', 'rank-math-pro' ),
'NG' => __( 'Nigeria', 'rank-math-pro' ),
'NU' => __( 'Niue', 'rank-math-pro' ),
'NF' => __( 'Norfolk Island', 'rank-math-pro' ),
'KP' => __( 'North Korea', 'rank-math-pro' ),
'NO' => __( 'Norway', 'rank-math-pro' ),
'OM' => __( 'Oman', 'rank-math-pro' ),
'PK' => __( 'Pakistan', 'rank-math-pro' ),
'PS' => __( 'Palestinian Territory', 'rank-math-pro' ),
'PA' => __( 'Panama', 'rank-math-pro' ),
'PG' => __( 'Papua New Guinea', 'rank-math-pro' ),
'PY' => __( 'Paraguay', 'rank-math-pro' ),
'PE' => __( 'Peru', 'rank-math-pro' ),
'PH' => __( 'Philippines', 'rank-math-pro' ),
'PN' => __( 'Pitcairn', 'rank-math-pro' ),
'PL' => __( 'Poland', 'rank-math-pro' ),
'PT' => __( 'Portugal', 'rank-math-pro' ),
'QA' => __( 'Qatar', 'rank-math-pro' ),
'IE' => __( 'Republic of Ireland', 'rank-math-pro' ),
'RE' => __( 'Reunion', 'rank-math-pro' ),
'RO' => __( 'Romania', 'rank-math-pro' ),
'RU' => __( 'Russia', 'rank-math-pro' ),
'RW' => __( 'Rwanda', 'rank-math-pro' ),
'ST' => __( 'São Tomé and Príncipe', 'rank-math-pro' ),
'BL' => __( 'Saint Barthélemy', 'rank-math-pro' ),
'SH' => __( 'Saint Helena', 'rank-math-pro' ),
'KN' => __( 'Saint Kitts and Nevis', 'rank-math-pro' ),
'LC' => __( 'Saint Lucia', 'rank-math-pro' ),
'SX' => __( 'Saint Martin (Dutch part)', 'rank-math-pro' ),
'MF' => __( 'Saint Martin (French part)', 'rank-math-pro' ),
'PM' => __( 'Saint Pierre and Miquelon', 'rank-math-pro' ),
'VC' => __( 'Saint Vincent and the Grenadines', 'rank-math-pro' ),
'SM' => __( 'San Marino', 'rank-math-pro' ),
'SA' => __( 'Saudi Arabia', 'rank-math-pro' ),
'SN' => __( 'Senegal', 'rank-math-pro' ),
'RS' => __( 'Serbia', 'rank-math-pro' ),
'SC' => __( 'Seychelles', 'rank-math-pro' ),
'SL' => __( 'Sierra Leone', 'rank-math-pro' ),
'SG' => __( 'Singapore', 'rank-math-pro' ),
'SK' => __( 'Slovakia', 'rank-math-pro' ),
'SI' => __( 'Slovenia', 'rank-math-pro' ),
'SB' => __( 'Solomon Islands', 'rank-math-pro' ),
'SO' => __( 'Somalia', 'rank-math-pro' ),
'ZA' => __( 'South Africa', 'rank-math-pro' ),
'GS' => __( 'South Georgia/Sandwich Islands', 'rank-math-pro' ),
'KR' => __( 'South Korea', 'rank-math-pro' ),
'SS' => __( 'South Sudan', 'rank-math-pro' ),
'ES' => __( 'Spain', 'rank-math-pro' ),
'LK' => __( 'Sri Lanka', 'rank-math-pro' ),
'SD' => __( 'Sudan', 'rank-math-pro' ),
'SR' => __( 'Suriname', 'rank-math-pro' ),
'SJ' => __( 'Svalbard and Jan Mayen', 'rank-math-pro' ),
'SZ' => __( 'Swaziland', 'rank-math-pro' ),
'SE' => __( 'Sweden', 'rank-math-pro' ),
'CH' => __( 'Switzerland', 'rank-math-pro' ),
'SY' => __( 'Syria', 'rank-math-pro' ),
'TW' => __( 'Taiwan', 'rank-math-pro' ),
'TJ' => __( 'Tajikistan', 'rank-math-pro' ),
'TZ' => __( 'Tanzania', 'rank-math-pro' ),
'TH' => __( 'Thailand', 'rank-math-pro' ),
'TL' => __( 'Timor-Leste', 'rank-math-pro' ),
'TG' => __( 'Togo', 'rank-math-pro' ),
'TK' => __( 'Tokelau', 'rank-math-pro' ),
'TO' => __( 'Tonga', 'rank-math-pro' ),
'TT' => __( 'Trinidad and Tobago', 'rank-math-pro' ),
'TN' => __( 'Tunisia', 'rank-math-pro' ),
'TR' => __( 'Turkey', 'rank-math-pro' ),
'TM' => __( 'Turkmenistan', 'rank-math-pro' ),
'TC' => __( 'Turks and Caicos Islands', 'rank-math-pro' ),
'TV' => __( 'Tuvalu', 'rank-math-pro' ),
'UG' => __( 'Uganda', 'rank-math-pro' ),
'UA' => __( 'Ukraine', 'rank-math-pro' ),
'AE' => __( 'United Arab Emirates', 'rank-math-pro' ),
'GB' => __( 'United Kingdom (UK)', 'rank-math-pro' ),
'US' => __( 'United States (US)', 'rank-math-pro' ),
'UY' => __( 'Uruguay', 'rank-math-pro' ),
'UZ' => __( 'Uzbekistan', 'rank-math-pro' ),
'VU' => __( 'Vanuatu', 'rank-math-pro' ),
'VA' => __( 'Vatican', 'rank-math-pro' ),
'VE' => __( 'Venezuela', 'rank-math-pro' ),
'VN' => __( 'Vietnam', 'rank-math-pro' ),
'WF' => __( 'Wallis and Futuna', 'rank-math-pro' ),
'EH' => __( 'Western Sahara', 'rank-math-pro' ),
'WS' => __( 'Western Samoa', 'rank-math-pro' ),
'YE' => __( 'Yemen', 'rank-math-pro' ),
'ZM' => __( 'Zambia', 'rank-math-pro' ),
'ZW' => __( 'Zimbabwe', 'rank-math-pro' ),
];
$cmb->add_field(
[
'id' => 'knowledgegraph_type',
'type' => 'radio_inline',
'name' => esc_html__( 'Person or Company', 'rank-math-pro' ),
'options' => [
'person' => esc_html__( 'Person', 'rank-math-pro' ),
'company' => esc_html__( 'Organization', 'rank-math-pro' ),
],
'desc' => esc_html__( 'Choose whether the site represents a person or an organization.', 'rank-math-pro' ),
'default' => 'person',
]
);
$cmb->add_field(
[
'id' => 'website_name',
'type' => 'text',
'name' => esc_html__( 'Website Name', 'rank-math-pro' ),
'desc' => esc_html__( 'Enter the name of your site to appear in search results.', 'rank-math-pro' ),
'default' => get_bloginfo( 'name' ),
]
);
$cmb->add_field(
[
'id' => 'website_alternate_name',
'type' => 'text',
'name' => esc_html__( 'Website Alternate Name', 'rank-math-pro' ),
'desc' => esc_html__( 'An alternate version of your site name (for example, an acronym or shorter name).', 'rank-math-pro' ),
]
);
$cmb->add_field(
[
'id' => 'knowledgegraph_name',
'type' => 'text',
'name' => esc_html__( 'Person/Organization Name', 'rank-math-pro' ),
'desc' => esc_html__( 'Your name or company name intended to feature in Google\'s Knowledge Panel.', 'rank-math-pro' ),
'default' => get_bloginfo( 'name' ),
]
);
$cmb->add_field(
[
'id' => 'knowledgegraph_logo',
'type' => 'file',
'name' => esc_html__( 'Logo', 'rank-math-pro' ),
'desc' => __( '<strong>Min Size: 112Χ112px</strong>.<br /> A squared image is preferred by the search engines.', 'rank-math-pro' ),
'options' => [ 'url' => false ],
]
);
$cmb->add_field(
[
'id' => 'url',
'type' => 'text_url',
'name' => esc_html__( 'URL', 'rank-math-pro' ),
'desc' => esc_html__( 'URL of the item.', 'rank-math-pro' ),
'default' => home_url(),
]
);
$cmb->add_field(
[
'id' => 'use_multiple_locations',
'type' => 'toggle',
'name' => esc_html__( 'Use Multiple Locations', 'rank-math-pro' ),
'desc' => esc_html__( 'Once you save the changes, we will create a new custom post type called "Locations" where you can add multiple locations of your business/organization.', 'rank-math-pro' ),
'options' => [
'off' => esc_html__( 'Default', 'rank-math-pro' ),
'on' => esc_html__( 'Custom', 'rank-math-pro' ),
],
'default' => 'off',
'dep' => $company,
]
);
$cmb->add_field(
[
'id' => 'email',
'type' => 'text',
'name' => esc_html__( 'Email', 'rank-math-pro' ),
'desc' => esc_html__( 'Search engines display your email address.', 'rank-math-pro' ),
]
);
$cmb->add_field(
[
'id' => 'phone',
'type' => 'text',
'name' => esc_html__( 'Phone', 'rank-math-pro' ),
'desc' => esc_html__( 'Search engines may prominently display your contact phone number for mobile users.', 'rank-math-pro' ),
'dep' => $person,
]
);
$cmb->add_field(
[
'id' => 'local_address',
'type' => 'address',
'name' => esc_html__( 'Address', 'rank-math-pro' ),
'dep' => [ [ 'use_multiple_locations', 'on', '!=' ] ],
]
);
$cmb->add_field(
[
'id' => 'local_address_format',
'type' => 'textarea_small',
'name' => esc_html__( 'Address Format', 'rank-math-pro' ),
'desc' => wp_kses_post( __( 'Format used when the address is displayed using the <code>[rank_math_contact_info]</code> shortcode.<br><strong>Available Tags: {address}, {locality}, {region}, {postalcode}, {country}, {gps}</strong>', 'rank-math-pro' ) ),
'default' => '{address} {locality}, {region} {postalcode}',
'classes' => 'rank-math-address-format',
'attributes' => [
'rows' => 2,
'placeholder' => '{address} {locality}, {region} {country}. {postalcode}.',
],
'dep' => $company,
]
);
$cmb->add_field(
[
'id' => 'local_business_type',
'type' => 'select',
'name' => esc_html__( 'Business Type', 'rank-math-pro' ),
'options' => Helper::choices_business_types( true ),
'attributes' => ( 'data-s2' ),
'dep' => $hide_on_multiple_locations,
]
);
$opening_hours = $cmb->add_field(
[
'id' => 'opening_hours',
'type' => 'group',
'name' => esc_html__( 'Opening Hours', 'rank-math-pro' ),
'desc' => esc_html__( 'Select opening hours. You can add multiple sets if you have different opening or closing hours on some days or if you have a mid-day break. Times are specified using 24:00 time.', 'rank-math-pro' ),
'options' => [
'add_button' => esc_html__( 'Add time', 'rank-math-pro' ),
'remove_button' => esc_html__( 'Remove', 'rank-math-pro' ),
],
'dep' => $hide_on_multiple_locations,
'classes' => 'cmb-group-text-only',
]
);
$cmb->add_group_field(
$opening_hours,
[
'id' => 'day',
'type' => 'select',
'options' => [
'Monday' => esc_html__( 'Monday', 'rank-math-pro' ),
'Tuesday' => esc_html__( 'Tuesday', 'rank-math-pro' ),
'Wednesday' => esc_html__( 'Wednesday', 'rank-math-pro' ),
'Thursday' => esc_html__( 'Thursday', 'rank-math-pro' ),
'Friday' => esc_html__( 'Friday', 'rank-math-pro' ),
'Saturday' => esc_html__( 'Saturday', 'rank-math-pro' ),
'Sunday' => esc_html__( 'Sunday', 'rank-math-pro' ),
],
]
);
$cmb->add_group_field(
$opening_hours,
[
'id' => 'time',
'type' => 'text',
'attributes' => [ 'placeholder' => esc_html__( 'e.g. 09:00-17:00', 'rank-math-pro' ) ],
]
);
$cmb->add_field(
[
'id' => 'opening_hours_format',
'type' => 'switch',
'name' => esc_html__( 'Opening Hours Format', 'rank-math-pro' ),
'options' => [
'off' => '24:00',
'on' => '12:00',
],
'desc' => esc_html__( 'Time format used in the contact shortcode.', 'rank-math-pro' ),
'default' => 'off',
'dep' => $company,
]
);
$phones = $cmb->add_field(
[
'id' => 'phone_numbers',
'type' => 'group',
'name' => esc_html__( 'Phone Number', 'rank-math-pro' ),
'desc' => esc_html__( 'Search engines may prominently display your contact phone number for mobile users.', 'rank-math-pro' ),
'options' => [
'add_button' => esc_html__( 'Add number', 'rank-math-pro' ),
'remove_button' => esc_html__( 'Remove', 'rank-math-pro' ),
],
'dep' => $hide_on_multiple_locations,
'classes' => 'cmb-group-text-only',
]
);
$cmb->add_group_field(
$phones,
[
'id' => 'type',
'type' => 'select',
'options' => Helper::choices_phone_types(),
'default' => 'customer_support',
]
);
$cmb->add_group_field(
$phones,
[
'id' => 'number',
'type' => 'text',
'attributes' => [ 'placeholder' => esc_html__( 'Format: +1-401-555-1212', 'rank-math-pro' ) ],
]
);
$cmb->add_field(
[
'id' => 'price_range',
'type' => 'text',
'name' => esc_html__( 'Price Range', 'rank-math-pro' ),
'desc' => esc_html__( 'The price range of the business, for example $$$.', 'rank-math-pro' ),
'dep' => $hide_on_multiple_locations,
]
);
$cmb->add_field(
[
'id' => 'hide_opening_hours',
'type' => 'switch',
'name' => esc_html__( 'Hide Opening Hours', 'rank-math-pro' ),
'desc' => esc_html__( 'Don\'t add opening hours data in Schema', 'rank-math-pro' ),
'options' => [
'off' => esc_html__( 'No', 'rank-math-pro' ),
'on' => esc_html__( 'Yes', 'rank-math-pro' ),
],
'default' => 'off',
'dep' => $use_multiple_locations,
]
);
$hide_opening_hours = [ 'relation' => 'and' ] + $use_multiple_locations;
$hide_opening_hours[] = [ 'hide_opening_hours', 'on', '!=' ];
$cmb->add_field(
[
'id' => 'closed_label',
'type' => 'text',
'name' => esc_html__( 'Closed label', 'rank-math-pro' ),
'desc' => esc_html__( 'Text to show in Opening hours when business is closed.', 'rank-math-pro' ),
'default' => 'Closed',
'dep' => $hide_opening_hours,
]
);
$cmb->add_field(
[
'id' => 'open_24_7',
'type' => 'text',
'name' => esc_html__( 'Open 24/7 label', 'rank-math-pro' ),
'desc' => esc_html__( 'Select the text to display alongside your opening hours when your store is open 24/7.', 'rank-math-pro' ),
'default' => 'Open 24/7',
'dep' => $hide_opening_hours,
]
);
$cmb->add_field(
[
'id' => 'open_24h',
'type' => 'text',
'name' => esc_html__( 'Open 24h label', 'rank-math-pro' ),
'default' => 'Open 24h',
'dep' => $hide_opening_hours,
]
);
$cmb->add_field(
[
'id' => 'map_unit',
'type' => 'select',
'name' => esc_html__( 'Measurement system', 'rank-math-pro' ),
'desc' => esc_html__( 'Select your preferred measurement system (miles or kilometers).', 'rank-math-pro' ),
'options' => [
'kilometers' => esc_html__( 'Kilometers', 'rank-math-pro' ),
'miles' => esc_html__( 'Miles', 'rank-math-pro' ),
],
'default' => 'kilometers',
'dep' => $use_multiple_locations,
]
);
$cmb->add_field(
[
'id' => 'map_style',
'type' => 'select',
'name' => esc_html__( 'Map Style', 'rank-math-pro' ),
'desc' => esc_html__( 'Select the map style you wish to use on the frontend of your website.', 'rank-math-pro' ),
'options' => [
'hybrid' => esc_html__( 'Hybrid', 'rank-math-pro' ),
'satellite' => esc_html__( 'Satellite', 'rank-math-pro' ),
'roadmap' => esc_html__( 'Roadmap', 'rank-math-pro' ),
'terrain' => esc_html__( 'Terrain', 'rank-math-pro' ),
],
'default' => 'hybrid',
'dep' => $use_multiple_locations,
]
);
$cmb->add_field(
[
'id' => 'limit_results',
'type' => 'text',
'name' => esc_html__( 'Maximum number of locations to show', 'rank-math-pro' ),
'desc' => esc_html__( 'Limit the number of locations shown on your website to those nearest your user.', 'rank-math-pro' ),
'default' => 10,
'dep' => $use_multiple_locations,
'attributes' => [
'type' => 'number',
'pattern' => '\d*',
'class' => 'small-text',
],
'sanitization_cb' => 'absint',
'escape_cb' => 'absint',
]
);
$cmb->add_field(
[
'id' => 'primary_country',
'type' => 'select',
'options' => $countries,
'name' => esc_html__( 'Primary Country', 'rank-math-pro' ),
'desc' => esc_html__( 'Select your organizations primary country of operation. This helps improve the accuracy of the store locator.', 'rank-math-pro' ),
'attributes' => ( 'data-s2' ),
'dep' => $use_multiple_locations,
]
);
$cmb->add_field(
[
'id' => 'route_label',
'type' => 'text',
'name' => esc_html__( 'Show Route label', 'rank-math-pro' ),
'desc' => esc_html__( 'Customize the label of the option users can use can click to get directions to your business location on the frontend.', 'rank-math-pro' ),
'default' => 'My Route',
'dep' => $use_multiple_locations,
]
);
$cmb->add_field(
[
'id' => 'enable_location_detection',
'type' => 'toggle',
'name' => esc_html__( 'Location Detection', 'rank-math-pro' ),
'desc' => esc_html__( 'Automatically detect the user\'s location as the starting point.', 'rank-math-pro' ),
'options' => [
'off' => esc_html__( 'Default', 'rank-math-pro' ),
'on' => esc_html__( 'Custom', 'rank-math-pro' ),
],
'default' => 'off',
'dep' => $use_multiple_locations,
]
);
$cmb->add_field(
[
'id' => 'same_organization_locations',
'type' => 'toggle',
'name' => esc_html__( 'All Locations are part of the same Organization', 'rank-math-pro' ),
'desc' => esc_html__( 'Enable if all of the locations where you serve customers are a part of the same legal entity.', 'rank-math-pro' ),
'options' => [
'off' => esc_html__( 'Default', 'rank-math-pro' ),
'on' => esc_html__( 'Custom', 'rank-math-pro' ),
],
'default' => 'off',
'dep' => $use_multiple_locations,
]
);
$cmb->add_field(
[
'id' => 'locations_enhanced_search',
'type' => 'toggle',
'name' => esc_html__( 'Enhanced Search', 'rank-math-pro' ),
'desc' => esc_html__( 'Include business locations in site-wide search results.', 'rank-math-pro' ),
'options' => [
'off' => esc_html__( 'Default', 'rank-math-pro' ),
'on' => esc_html__( 'Custom', 'rank-math-pro' ),
],
'default' => 'off',
'dep' => $use_multiple_locations,
]
);
$cmb->add_field(
[
'id' => 'maps_api_key',
'type' => 'text',
'name' => esc_html__( 'Google Maps API Key', 'rank-math-pro' ),
/* translators: %s expands to "Google Maps Embed API" https://developers.google.com/maps/documentation/embed/ */
'desc' => sprintf( esc_html__( 'An API Key is required to display embedded Google Maps on your site. Get it here: %s', 'rank-math-pro' ), '<a href="https://developers.google.com/maps/documentation/javascript/get-api-key" target="_blank">' . __( 'Google Maps Embed API', 'rank-math-pro' ) . '</a>' ),
'dep' => $company,
'attributes' => [ 'type' => 'password' ],
]
);
$cmb->add_field(
[
'id' => 'geo',
'type' => 'text',
'name' => esc_html__( 'Geo Coordinates', 'rank-math-pro' ),
'desc' => esc_html__( 'Latitude and longitude values separated by comma.', 'rank-math-pro' ),
'dep' => $company,
]
);
$cmb->add_field(
[
'id' => 'locations_post_type_base',
'type' => 'text',
'name' => esc_html__( 'Locations Post Type Base', 'rank-math-pro' ),
'default' => 'locations',
'desc' => '<code>' . home_url( 'locations/africa/' ) . '</code>',
'dep' => $use_multiple_locations,
]
);
$cmb->add_field(
[
'id' => 'locations_category_base',
'type' => 'text',
'name' => esc_html__( 'Locations Category Base', 'rank-math-pro' ),
'default' => 'locations-category',
'desc' => '<code>' . home_url( 'locations-category/regional-offices/' ) . '</code>',
'dep' => $use_multiple_locations,
]
);
$cmb->add_field(
[
'id' => 'locations_post_type_label',
'type' => 'text',
'name' => esc_html__( 'Location Post Type Name', 'rank-math-pro' ),
'default' => 'RM Locations',
'desc' => esc_html__( 'The label that appears in the sidebar for the custom post type where you can add & manage locations.', 'rank-math-pro' ),
'dep' => $use_multiple_locations,
]
);
$cmb->add_field(
[
'id' => 'locations_post_type_plural_label',
'type' => 'text',
'name' => esc_html__( 'Locations Post Type Name (Plural)', 'rank-math-pro' ),
'default' => 'RM Locations',
'desc' => esc_html__( 'As above, but the label that would be applicable for more than one location (default: RM Locations).', 'rank-math-pro' ),
'dep' => $use_multiple_locations,
]
);
$about_page = Helper::get_settings( 'titles.local_seo_about_page' );
$about_options = [ '' => __( 'Select Page', 'rank-math-pro' ) ];
if ( $about_page ) {
$about_options[ $about_page ] = get_the_title( $about_page );
}
$cmb->add_field(
[
'id' => 'local_seo_about_page',
'type' => 'select',
'options' => $about_options,
'name' => esc_html__( 'About Page', 'rank-math-pro' ),
'desc' => esc_html__( 'Select a page on your site where you want to show the LocalBusiness meta data.', 'rank-math-pro' ),
'attributes' => ( 'data-s2-pages' ),
]
);
$contact_page = Helper::get_settings( 'titles.local_seo_contact_page' );
$contact_options = [ '' => __( 'Select Page', 'rank-math-pro' ) ];
if ( $contact_page ) {
$contact_options[ $contact_page ] = get_the_title( $contact_page );
}
$cmb->add_field(
[
'id' => 'local_seo_contact_page',
'type' => 'select',
'options' => $contact_options,
'name' => esc_html__( 'Contact Page', 'rank-math-pro' ),
'desc' => esc_html__( 'Select a page on your site where you want to show the LocalBusiness meta data.', 'rank-math-pro' ),
'attributes' => ( 'data-s2-pages' ),
]
);