/home/lnzliplg/www/aioseo-local-business.tar
aioseo-local-business.php 0000644 00000006572 15172727762 0011507 0 ustar 00 <?php
/**
* Plugin Name: AIOSEO - Local Business
* Plugin URI: https://aioseo.com
* Description: Adds Local Business support to All in One SEO.
* Author: All in One SEO Team
* Author URI: https://aioseo.com
* Version: 1.3.3
* Text Domain: aioseo-local-business
* Domain Path: languages
*
* All in One SEO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* any later version.
*
* All in One SEO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with All in One SEO. If not, see <https://www.gnu.org/licenses/>.
*
* @since 1.0.0
* @author All in One SEO
* @package AIOSEO\Extend\LocalBusiness
* @license GPL-2.0+
* @copyright Copyright (c) 2020, All in One SEO
*/
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
// Plugin constants.
define( 'AIOSEO_LOCAL_BUSINESS_FILE', __FILE__ );
define( 'AIOSEO_LOCAL_BUSINESS_DIR', __DIR__ );
define( 'AIOSEO_LOCAL_BUSINESS_PATH', plugin_dir_path( AIOSEO_LOCAL_BUSINESS_FILE ) );
define( 'AIOSEO_LOCAL_BUSINESS_URL', plugin_dir_url( AIOSEO_LOCAL_BUSINESS_FILE ) );
// Require our translation downloader.
require_once __DIR__ . '/extend/translations.php';
add_action( 'init', 'aioseo_local_business_translations' );
function aioseo_local_business_translations() {
$translations = new AIOSEOTranslations(
'plugin',
'aioseo-local-business',
'https://aioseo.com/aioseo-plugin/aioseo-local-business/packages.json'
);
$translations->init();
// @NOTE: The slugs here need to stay as aioseo-addon.
$addonTranslations = new AIOSEOTranslations(
'plugin',
'aioseo-addon',
'https://aioseo.com/aioseo-plugin/aioseo-addon/packages.json'
);
$addonTranslations->init();
}
// Require our plugin compatibility checker.
require_once __DIR__ . '/extend/init.php';
// Check if this plugin should be disabled.
if ( aioseoAddonIsDisabled( 'aioseo-local-business' ) ) {
return;
}
// Plugin compatibility checks.
new AIOSEOExtend( 'AIOSEO - Local Business', 'aioseo_local_business_load', AIOSEO_LOCAL_BUSINESS_FILE, '4.6.4' );
/**
* Function to load the addon.
*
* @since 1.0.0
*
* @return void
*/
function aioseo_local_business_load() {
$levels = aioseo()->addons->getAddonLevels( 'aioseo-local-business' );
$extend = new AIOSEOExtend( 'AIOSEO - Local Business', '', AIOSEO_LOCAL_BUSINESS_FILE, '4.6.4', $levels );
$addon = aioseo()->addons->getAddon( 'aioseo-local-business' );
if ( ! $addon->hasMinimumVersion ) {
$extend->requiresUpdate();
return;
}
if ( ! aioseo()->pro ) {
$extend->requiresPro();
return;
}
// We don't want to return if the plan is only expired.
if ( aioseo()->license->isExpired() ) {
$extend->requiresUnexpiredLicense();
$extend->disableNotices = true;
}
if ( aioseo()->license->isInvalid() || aioseo()->license->isDisabled() ) {
$extend->requiresActiveLicense();
return;
}
if ( ! aioseo()->license->isAddonAllowed( 'aioseo-local-business' ) ) {
$extend->requiresPlanLevel();
return;
}
require_once __DIR__ . '/app/LocalBusiness.php';
aioseoLocalBusiness();
} extend/init.php 0000644 00000034433 15172727763 0007537 0 ustar 00 <?php
// phpcs:disable Generic.Arrays.DisallowLongArraySyntax.Found
// If the class exists already don't redeclare.
if ( ! class_exists( 'AIOSEOExtend' ) ) {
/**
* This class checks for compatibility for this plugin to load.
*
* @since 1.0.0
*/
class AIOSEOExtend {
/**
* The addon name.
*
* @since 1.0.0
*
* @var string
*/
private $name = '';
/**
* The function name.
*
* @since 1.0.0
*
* @var string
*/
private $function = '';
/**
* The filename.
*
* @since 1.0.0
*
* @var string
*/
private $file = '';
/**
* The minimum version.
*
* @since 1.0.0
*
* @var string
*/
private $minimumVersion = '';
/**
* The required plan levels.
*
* @since 1.0.0
*
* @var array
*/
private $levels = array();
/**
* Whether to disable other notices.
*
* @since 1.0.0
*
* @var bool
*/
public $disableNotices = false;
/**
* Holds the active AIOSEO Pro version.
*
* @since 1.0.0
*
* @var string
*/
public static $aioseoVersion = '';
/**
* Holds the addon notices.
*
* @since 1.0.0
*
* @var string
*/
public static $addonNotices = array();
/**
* The construct function.
*
* @since 1.0.0
*
* @param string $name The name of the addon.
* @param string $function The name of the function to call once we pass compatibility checks.
* @param string $file The addon file to deactivate if checks fail.
* @param string $minimumVersion The minimum version of our plugin we can activate against.
* @param array $levels The levels that this addon support.
*/
public function __construct( $name, $function, $file, $minimumVersion, $levels = array() ) {
$this->name = $name;
$this->function = $function;
$this->file = $file;
$this->minimumVersion = $minimumVersion;
$this->levels = $levels;
add_action( 'plugins_loaded', array( $this, 'init' ) );
}
/**
* Check addon requirements.
* We do it on `plugins_loaded` hook. If earlier the core constants are still not defined.
*
* @since 1.0.0
*
* @return void
*/
public function init() {
if ( version_compare( PHP_VERSION, '7.0', '<' ) ) {
$this->failPhp();
return;
}
// Since the version numbers may vary, we only want to compare the first 3 numbers.
self::$aioseoVersion = defined( 'AIOSEO_VERSION' ) ? current( explode( '-', AIOSEO_VERSION ) ) : '';
if ( ! has_action( 'admin_notices', array( __CLASS__, 'adminNotices' ) ) ) {
add_action( 'admin_notices', array( __CLASS__, 'adminNotices' ) );
}
if (
empty( self::$aioseoVersion ) ||
version_compare( self::$aioseoVersion, $this->minimumVersion, '<' )
) {
$this->requiresPro();
add_filter( 'auto_update_plugin', array( $this, 'disableAutoUpdate' ), 10, 2 );
add_filter( 'plugin_auto_update_setting_html', array( $this, 'modifyAutoupdaterSettingHtml' ), 11, 2 );
return;
}
add_action( 'aioseo_loaded', $this->function, 10 );
}
/**
* Prints out all notices.
*
* @since 1.0.0
*
* @return void
*/
public static function adminNotices() {
// Double check we're actually in the admin before outputting anything.
if ( ! is_admin() ) {
return;
}
self::showAddonsNotice( 'FailPhpVersion', sprintf(
// Translators: 1 - Opening link tag, 2 - Closing link tag.
esc_html__( 'Your site is running an outdated version of PHP that is no longer supported and is not compatible with the following addons (%1$sRead more%2$s for additional information):', 'aioseo-addon' ), // phpcs:ignore Generic.Files.LineLength.MaxExceeded
'<a href="https://aioseo.com/docs/supported-php-version/" target="_blank" rel="noopener noreferrer">',
'</a>'
) );
self::showAddonsNotice( 'FailUpdate', sprintf(
// Translators: 1 - "All in One SEO 4.0.0".
esc_html__( 'The following addons cannot be used, because they require an update to work with %1$s:', 'aioseo-addon' ),
'<strong>All in One SEO Pro ' . wp_kses_post( self::$aioseoVersion ) . '</strong>' // We need to put the name here in since the plugin is most likely not active.
) );
self::showAddonsNotice( 'FailActiveLicense', sprintf(
// Translators: 1 - "All in One SEO", 2 - Opening HTML link tag, 3 - Closing HTML link tag.
esc_html__( 'The following addons cannot be used, because they require an active license for %1$s. Your license is missing or has expired. To verify your subscription, please %2$svisit our website%3$s.', 'aioseo-addon' ), // phpcs:ignore Generic.Files.LineLength.MaxExceeded
esc_html( defined( 'AIOSEO_PLUGIN_NAME' ) ? AIOSEO_PLUGIN_NAME : 'All in One SEO' ),
'<a target="_blank" href="' . self::getUtmUrl( 'account/', 'FailActiveLicense', 'fail-valid-license' ) . '">', // phpcs:ignore WordPress.Security.EscapeOutput, Generic.Files.LineLength.MaxExceeded
'</a>'
) );
self::showMinimumVersionAddonsNotice( 'FailProVersion', sprintf(
// Translators: 1 - "All in One SEO 4.0.0".
esc_html__( 'The following addons cannot be used, because they require %1$s or later to work:', 'aioseo-addon' ),
'<strong>All in One SEO Pro [minimumVersion]</strong>'
) );
self::showAddonsNotice( 'FailPlanExpired', sprintf(
// Translators: 1 - Opening HTML link tag, 2 - Closing HTML link tag.
esc_html__( 'The following addons cannot be used, because your plan has expired. To renew your subscription, please %1$svisit our website%2$s.', 'aioseo-addon' ),
'<a target="_blank" href="' . self::getUtmUrl( 'account/subscriptions/', 'FailPlanExpired', 'fail-plan-expired' ) . '">', // phpcs:ignore WordPress.Security.EscapeOutput, Generic.Files.LineLength.MaxExceeded
'</a>'
) );
$level = '';
if ( self::$aioseoVersion ) {
$level = aioseo()->internalOptions->internal->has( 'license' ) && aioseo()->internalOptions->internal->license->level
? aioseo()->internalOptions->internal->license->level
: $level;
if ( ! $level ) {
if ( aioseo()->core->cache->get( 'failed_update' ) ) {
return;
}
$level = esc_html__( 'Unlicensed', 'aioseo-addon' );
}
}
self::showAddonsNotice( 'FailPlanLevel', sprintf(
// Translators: 1 - The current plan name, 2 - Opening HTML link tag, 3 - Closing HTML link tag.
esc_html__( 'The following addons cannot be used, because your plan level %1$s does not include access to these addons. To upgrade your subscription, please %2$svisit our website%3$s.', 'aioseo-addon' ), // phpcs:ignore Generic.Files.LineLength.MaxExceeded
'<strong>(' . ( ! empty( $level ) ? wp_kses_post( ucfirst( $level ) ) : '' ) . ')</strong>',
'<a target="_blank" href="' . self::getUtmUrl( 'pro-upgrade/', 'FailPlanLevel', 'fail-plan-level' ) . '">', // phpcs:ignore WordPress.Security.EscapeOutput, Generic.Files.LineLength.MaxExceeded
'</a>'
) );
}
/**
* Get the current notice.
*
* @since 1.0.0
*
* @param string $noticeKey The notice key.
* @return string The current notice.
*/
public static function getCurrentNotice( $noticeKey ) {
$noticeKey = 'aioseoAddon' . $noticeKey;
if ( empty( self::$addonNotices[ $noticeKey ] ) ) {
return '';
}
return current( self::$addonNotices[ $noticeKey ] );
}
/**
* Get the URL for the current notice.
*
* @since 1.0.0
*
* @param string $uri The URL to append to the marketing site.
* @param string $noticeKey The notice key.
* @param string $content The UTM content parameter.
* @return string The current notice.
*/
public static function getUtmUrl( $uri, $noticeKey, $content ) {
$url = 'https://aioseo.com/' . $uri;
// Generate the new arguments.
$args = [
'utm_source' => 'WordPress',
'utm_campaign' => 'addon',
'utm_medium' => self::getCurrentNotice( $noticeKey ),
'utm_content' => $content
];
// Return the new URL.
$url = add_query_arg( $args, $url );
return esc_url( $url );
}
/**
* Adds a generic notice for an addon.
*
* @since 1.0.0
*
* @param string $noticeKey The notice key.
* @param string $addonName The addon name.
* @return void
*/
public function addAddonNotice( $noticeKey, $addonName ) {
if ( $this->disableNotices ) {
return;
}
$noticeKey = 'aioseoAddon' . $noticeKey;
if ( empty( self::$addonNotices[ $noticeKey ] ) ) {
self::$addonNotices[ $noticeKey ] = array();
}
self::$addonNotices[ $noticeKey ][] = [
'addonName' => $addonName,
'minimumVersion' => $this->minimumVersion
];
}
/**
* HTML for the addon notice.
*
* @since 1.0.0
*
* @param string $noticeKey The notice key.
* @param string $message The message to output.
* @return void
*/
public static function showAddonsNotice( $noticeKey, $message ) {
$noticeKey = 'aioseoAddon' . $noticeKey;
if ( empty( self::$addonNotices[ $noticeKey ] ) ) {
return;
}
echo '<div class="notice notice-error"><p>';
echo wp_kses_post( $message );
echo '</p>';
$addonsList = wp_list_pluck( self::$addonNotices[ $noticeKey ], 'addonName' );
$addonsList = implode( '</strong></li><li><strong>', $addonsList );
echo '<ul><li><strong>' . wp_kses_post( $addonsList ) . '</strong></li></ul>';
echo '</div>';
if ( isset( $_GET['activate'] ) ) { // phpcs:ignore HM.Security.NonceVerification.Recommended
unset( $_GET['activate'] );
}
}
/**
* HTML for the addon notice.
*
* @since 1.0.0
*
* @param string $noticeKey The notice key.
* @param string $message The message to output.
* @return void
*/
public static function showMinimumVersionAddonsNotice( $noticeKey, $message ) {
$noticeKey = 'aioseoAddon' . $noticeKey;
if ( empty( self::$addonNotices[ $noticeKey ] ) ) {
return;
}
$versions = array_unique( wp_list_pluck( self::$addonNotices[ $noticeKey ], 'minimumVersion' ) );
sort( $versions );
foreach ( $versions as $version ) {
$versionMessage = str_replace( '[minimumVersion]', $version, $message );
$addonsList = wp_filter_object_list( self::$addonNotices[ $noticeKey ], [ 'minimumVersion' => $version ], 'and', 'addonName' );
echo '<div class="notice notice-error"><p>';
echo wp_kses_post( $versionMessage );
echo '</p>';
$addonsList = implode( '</strong></li><li><strong>', $addonsList );
echo '<ul><li><strong>' . wp_kses_post( $addonsList ) . '</strong></li></ul>';
echo '</div>';
}
if ( isset( $_GET['activate'] ) ) { // phpcs:ignore HM.Security.NonceVerification.Recommended
unset( $_GET['activate'] );
}
}
/**
* Throws a notice if PHP version is too low.
*
* @since 1.0.0
*
* @return void
*/
public function failPhp() {
$this->addAddonNotice( 'FailPhpVersion', $this->name );
}
/**
* A secondary function to call if Pro is not active.
*
* @since 1.0.0
*
* @return void
*/
public function requiresPro() {
$this->addAddonNotice( 'FailProVersion', $this->name );
}
/**
* A secondary function to call if Pro is not active.
*
* @since 1.0.0
*
* @return void
*/
public function requiresUpdate() {
$this->addAddonNotice( 'FailUpdate', $this->name );
}
/**
* A secondary function to call if an active license is not found.
*
* @since 1.0.0
*
* @return void
*/
public function requiresActiveLicense() {
$this->addAddonNotice( 'FailActiveLicense', $this->name );
}
/**
* A secondary function to call if an expired license is found.
*
* @since 1.0.0
*
* @return void
*/
public function requiresUnexpiredLicense() {
$this->addAddonNotice( 'FailPlanExpired', $this->name );
}
/**
* A secondary function to call if an active license is not found.
*
* @since 1.0.0
*
* @return void
*/
public function requiresPlanLevel() {
$this->addAddonNotice( 'FailPlanLevel', $this->name );
}
/**
* Disable auto-update.
*
* @since 1.0.0
*
* @param bool $update Flag to update the plugin or not.
* @param object $item Update data about a specific plugin.
* @return bool Whether or not to auto update.
*/
public function disableAutoUpdate( $update, $item ) {
// If this is multisite and is not on the main site, return early.
if ( is_multisite() && ! is_main_site() ) {
return $update;
}
if (
! empty( $item->plugin ) &&
plugin_basename( $this->file ) === $item->plugin
) {
return false;
}
return $update;
}
/**
* Display AIOSEO Pro CTA on Plugins -> autoupdater setting column
*
* @since 1.0.0
*
* @param string $html
* @param string $pluginFile
* @return string The HTML.
*/
public function modifyAutoupdaterSettingHtml( $html, $pluginFile ) {
if ( plugin_basename( $this->file ) === $pluginFile &&
// If main plugin (free) happens to be enabled and already takes care of this, then bail
! apply_filters( "aioseo_is_autoupdate_setting_html_filtered_$pluginFile", false )
) {
$html = sprintf(
'<a href="%s" target="_blank">%s</a>',
"https://aioseo.com/docs/how-to-upgrade-from-all-in-one-seo-lite-to-pro/?utm_source=liteplugin&utm_medium=plugins-autoupdate&utm_campaign=upgrade-to-autoupdate&utm_content={$this->name}", // phpcs:ignore Generic.Files.LineLength.MaxExceeded
// Translators: 1 - "AIOSEO Pro"
sprintf( esc_html__( 'Enable the %1$s plugin to manage auto-updates', 'aioseo-addon' ), 'AIOSEO Pro' )
);
}
return $html;
}
}
}
if ( ! function_exists( 'aioseoAddonIsDisabled' ) ) {
/**
* Disable the current addon if triggered externally.
*
* @since 1.0.0
*
* @param string $slug The addon slug.
* @return bool True if the addon should be disabled.
*/
function aioseoAddonIsDisabled( $slug ) {
if ( ! defined( 'AIOSEO_DEV_VERSION' ) && ! isset( $_REQUEST['aioseo-dev'] ) ) { // phpcs:ignore HM.Security.NonceVerification.Recommended
return false;
}
if ( ! isset( $_REQUEST['aioseo-disable-addon'] ) ) { // phpcs:ignore HM.Security.NonceVerification.Recommended
return false;
}
$request = wp_unslash( $_REQUEST['aioseo-disable-addon'] ); // phpcs:ignore HM.Security
$request = explode( ',', $request );
foreach ( $request as $r ) {
if ( 0 !== strpos( $r, 'aioseo' ) ) {
$r = 'aioseo-' . $r;
}
if ( $slug === $r ) {
return true;
}
}
return false;
}
} extend/translations.php 0000644 00000015272 15172727763 0011315 0 ustar 00 <?php
// phpcs:disable Generic.Arrays.DisallowLongArraySyntax.Found
// If the class exists already don't redeclare.
if ( ! class_exists( 'AIOSEOTranslations' ) ) {
/**
* This class pulls in translations for the current addon.
*
* @since 1.0.0
*/
class AIOSEOTranslations {
/**
* The project type.
*
* @since 1.0.0
*
* @var string
*/
private $type = '';
/**
* The project dir slug.
*
* @since 1.0.0
*
* @var string
*/
private $slug = '';
/**
* The GlotPress API URL.
*
* @since 1.0.0
*
* @var string
*/
private $apiUrl = '';
/**
* Installed translations.
*
* @since 1.0.0
*
* @var array
*/
private static $installedTranslations = array();
/**
* Available languages.
*
* @since 1.0.0
*
* @var array
*/
private static $availableLanguages = array();
/**
* Class constructor.
*
* @param string $type Project type. Either plugin or theme.
* @param string $slug Project directory slug.
* @param string $apiUrl Full GlotPress API URL for the project.
*/
public function __construct( $type, $slug, $apiUrl ) {
$this->type = $type;
$this->slug = $slug;
$this->apiUrl = $apiUrl;
}
/**
* Adds a new project to load translations for.
*
* @since 1.0.0
*
* @return void
*/
public function init() {
if ( ! has_action( 'init', [ $this, 'registerCleanTranslationsCache' ] ) ) {
add_action( 'init', [ $this, 'registerCleanTranslationsCache' ], 9999 );
}
// Short-circuits translations API requests for private projects.
add_filter(
'translations_api',
function ( $result, $requestedType, $args ) {
if ( $this->type . 's' === $requestedType && $this->slug === $args['slug'] ) {
return $this->getTranslations( $this->type, $args['slug'], $this->apiUrl );
}
return $result;
},
10,
3
);
// Filters the translations transients to include the private plugin or theme. @see wp_get_translation_updates().
add_filter(
'site_transient_update_' . $this->type . 's',
function ( $value ) {
if ( ! $value ) {
$value = new \stdClass();
}
if ( ! is_object( $value ) ) {
// If the value isn't an object at this point, bail in order to prevent errors.
return $value;
}
if ( ! isset( $value->translations ) || ! is_array( $value->translations ) ) {
$value->translations = [];
}
$translations = $this->getTranslations( $this->type, $this->slug, $this->apiUrl );
if ( ! isset( $translations[ $this->slug ]['translations'] ) ) {
return $value;
}
if ( empty( self::$installedTranslations ) ) {
self::$installedTranslations = wp_get_installed_translations( $this->type . 's' );
}
if ( empty( self::$availableLanguages ) ) {
self::$availableLanguages = get_available_languages();
}
foreach ( (array) $translations[ $this->slug ]['translations'] as $translation ) {
if ( in_array( $translation['language'], self::$availableLanguages, true ) ) {
if ( isset( self::$installedTranslations[ $this->slug ][ $translation['language'] ] ) && $translation['updated'] ) {
$local = new DateTime( self::$installedTranslations[ $this->slug ][ $translation['language'] ]['PO-Revision-Date'] );
$remote = new DateTime( $translation['updated'] );
if ( $local >= $remote ) {
continue;
}
}
$translation['type'] = $this->type;
$translation['slug'] = $this->slug;
$value->translations[] = $translation;
}
}
return $value;
}
);
}
/**
* Registers actions for clearing translation caches.
*
* @since 1.0.0
*
* @return void
*/
public function registerCleanTranslationsCache() {
$clearPluginTranslations = function() {
$this->cleanTranslationsCache( 'plugin' );
};
$clearThemeTranslations = function() {
$this->cleanTranslationsCache( 'theme' );
};
add_action( 'set_site_transient_update_plugins', $clearPluginTranslations );
add_action( 'delete_site_transient_update_plugins', $clearPluginTranslations );
add_action( 'set_site_transient_update_themes', $clearThemeTranslations );
add_action( 'delete_site_transient_update_themes', $clearThemeTranslations );
}
/**
* Clears existing translation cache for a given type.
*
* @since 1.0.0
*
* @param string $type Project type. Either plugin or theme.
* @return void
*/
public function cleanTranslationsCache( $type ) {
$transientKey = '_aioseo_translations_' . $this->slug . '_' . $type;
if ( is_multisite() ) {
switch_to_blog( get_network()->site_id );
}
$translations = get_site_transient( $transientKey );
if ( is_multisite() ) {
restore_current_blog();
}
if ( ! is_array( $translations ) ) {
return;
}
// Don't delete the cache if the transient gets changed multiple times
// during a single request. Set cache lifetime to maximum 15 seconds.
$cacheLifespan = 15;
$timeNotChanged = isset( $translations['_last_checked'] ) && ( time() - $translations['_last_checked'] ) > $cacheLifespan;
if ( ! $timeNotChanged ) {
return;
}
if ( is_multisite() ) {
switch_to_blog( get_network()->site_id );
}
delete_site_transient( $transientKey );
if ( is_multisite() ) {
restore_current_blog();
}
}
/**
* Gets the translations for a given project.
*
* @since 1.0.0
*
* @param string $type Project type. Either plugin or theme.
* @param string $slug Project directory slug.
* @param string $url Full GlotPress API URL for the project.
* @return array Translation data.
*/
public function getTranslations( $type, $slug, $url ) {
$transientKey = '_aioseo_translations_' . $slug . '_' . $type;
if ( is_multisite() ) {
switch_to_blog( get_network()->site_id );
}
$translations = get_site_transient( $transientKey );
if ( is_multisite() ) {
restore_current_blog();
}
if ( false !== $translations && is_array( $translations ) ) {
return $translations;
}
if ( ! is_array( $translations ) ) {
$translations = [];
}
if ( isset( $translations[ $slug ] ) && is_array( $translations[ $slug ] ) ) {
return $translations[ $slug ];
}
$result = json_decode( wp_remote_retrieve_body( wp_remote_get( $url, [ 'timeout' => 2 ] ) ), true );
if ( ! is_array( $result ) ) {
$result = [];
}
$translations[ $slug ] = $result;
$translations['_last_checked'] = time();
if ( is_multisite() ) {
switch_to_blog( get_network()->site_id );
}
set_site_transient( $transientKey, $translations );
if ( is_multisite() ) {
restore_current_blog();
}
return $result;
}
}
} dist/js/map.DRPxR061.js 0000644 00000002305 15172727763 0010444 0 ustar 00 document.addEventListener(window.aioseoMapOptions.mapLoadEvent,function(e){if(e.detail===null||!e.detail||!e.detail.element||!e.detail.mapOptions)return;const n=document.querySelector(e.detail.element);if(!n||n.className.match(/map-loaded/))return;if(e.detail.placeId){const a=document.createElement("iframe");a.style.width=e.detail.instance.width,a.style.height=e.detail.instance.height,a.style.border="0",a.frameborder="0",a.src="https://www.google.com/maps/embed/v1/place?key="+window.aioseoMapOptions.apiKey+"&q=place_id:"+e.detail.placeId,n.replaceChildren(a),n.className+=" map-loaded";return}new google.maps.plugins.loader.Loader({apiKey:window.aioseoMapOptions.apiKey,libraries:["places"]}).load().then(a=>{const t=new a.maps.Map(n,e.detail.mapOptions),i=new a.maps.Marker({map:t,position:e.detail.mapOptions.center,icon:e.detail.customMarker?{url:e.detail.customMarker,origin:new a.maps.Point(0,0),anchor:new a.maps.Point(17,34),scaledSize:new a.maps.Size(25,25)}:null});if(e.detail.infoWindowContent){const o=new a.maps.InfoWindow({content:e.detail.infoWindowContent});o.open(t,i),i.addListener("click",()=>{o.open({anchor:i,map:t,shouldFocus:!1})})}n.className+=" map-loaded"}).catch(a=>{console.error(a)})});
dist/js/js-api-loader.liRm3N-P.js 0000644 00000054703 15172727763 0012442 0 ustar 00 /* @googlemaps/js-api-loader 1.12.1 */
this.google=this.google||{},this.google.maps=this.google.maps||{},this.google.maps.plugins=this.google.maps.plugins||{},this.google.maps.plugins.loader=function(t){"use strict";function e(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}var n="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function r(t,e){return t(e={exports:{}},e.exports),e.exports}var o=function(t){return t&&t.Math==Math&&t},i=o("object"==typeof globalThis&&globalThis)||o("object"==typeof window&&window)||o("object"==typeof self&&self)||o("object"==typeof n&&n)||function(){return this}()||Function("return this")(),c=function(t){try{return!!t()}catch(t){return!0}},a=!c((function(){return 7!=Object.defineProperty({},1,{get:function(){return 7}})[1]})),u={}.propertyIsEnumerable,s=Object.getOwnPropertyDescriptor,f={f:s&&!u.call({1:2},1)?function(t){var e=s(this,t);return!!e&&e.enumerable}:u},l=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}},h={}.toString,p=function(t){return h.call(t).slice(8,-1)},d="".split,v=c((function(){return!Object("z").propertyIsEnumerable(0)}))?function(t){return"String"==p(t)?d.call(t,""):Object(t)}:Object,g=function(t){if(null==t)throw TypeError("Can't call method on "+t);return t},y=function(t){return v(g(t))},m=function(t){return"object"==typeof t?null!==t:"function"==typeof t},b=function(t,e){if(!m(t))return t;var n,r;if(e&&"function"==typeof(n=t.toString)&&!m(r=n.call(t)))return r;if("function"==typeof(n=t.valueOf)&&!m(r=n.call(t)))return r;if(!e&&"function"==typeof(n=t.toString)&&!m(r=n.call(t)))return r;throw TypeError("Can't convert object to primitive value")},w=function(t){return Object(g(t))},S={}.hasOwnProperty,j=Object.hasOwn||function(t,e){return S.call(w(t),e)},O=i.document,E=m(O)&&m(O.createElement),k=function(t){return E?O.createElement(t):{}},T=!a&&!c((function(){return 7!=Object.defineProperty(k("div"),"a",{get:function(){return 7}}).a})),L=Object.getOwnPropertyDescriptor,P={f:a?L:function(t,e){if(t=y(t),e=b(e,!0),T)try{return L(t,e)}catch(t){}if(j(t,e))return l(!f.f.call(t,e),t[e])}},M=function(t){if(!m(t))throw TypeError(String(t)+" is not an object");return t},x=Object.defineProperty,C={f:a?x:function(t,e,n){if(M(t),e=b(e,!0),M(n),T)try{return x(t,e,n)}catch(t){}if("get"in n||"set"in n)throw TypeError("Accessors not supported");return"value"in n&&(t[e]=n.value),t}},_=a?function(t,e,n){return C.f(t,e,l(1,n))}:function(t,e,n){return t[e]=n,t},A=function(t,e){try{_(i,t,e)}catch(n){i[t]=e}return e},I="__core-js_shared__",N=i[I]||A(I,{}),R=Function.toString;"function"!=typeof N.inspectSource&&(N.inspectSource=function(t){return R.call(t)});var D,F,G,K,V=N.inspectSource,B=i.WeakMap,z="function"==typeof B&&/native code/.test(V(B)),U=r((function(t){(t.exports=function(t,e){return N[t]||(N[t]=void 0!==e?e:{})})("versions",[]).push({version:"3.14.0",mode:"global",copyright:"© 2021 Denis Pushkarev (zloirock.ru)"})})),H=0,q=Math.random(),W=function(t){return"Symbol("+String(void 0===t?"":t)+")_"+(++H+q).toString(36)},J=U("keys"),Y={},Q="Object already initialized",X=i.WeakMap;if(z||N.state){var Z=N.state||(N.state=new X),$=Z.get,tt=Z.has,et=Z.set;D=function(t,e){if(tt.call(Z,t))throw new TypeError(Q);return e.facade=t,et.call(Z,t,e),e},F=function(t){return $.call(Z,t)||{}},G=function(t){return tt.call(Z,t)}}else{var nt=J[K="state"]||(J[K]=W(K));Y[nt]=!0,D=function(t,e){if(j(t,nt))throw new TypeError(Q);return e.facade=t,_(t,nt,e),e},F=function(t){return j(t,nt)?t[nt]:{}},G=function(t){return j(t,nt)}}var rt,ot,it={set:D,get:F,has:G,enforce:function(t){return G(t)?F(t):D(t,{})},getterFor:function(t){return function(e){var n;if(!m(e)||(n=F(e)).type!==t)throw TypeError("Incompatible receiver, "+t+" required");return n}}},ct=r((function(t){var e=it.get,n=it.enforce,r=String(String).split("String");(t.exports=function(t,e,o,c){var a,u=!!c&&!!c.unsafe,s=!!c&&!!c.enumerable,f=!!c&&!!c.noTargetGet;"function"==typeof o&&("string"!=typeof e||j(o,"name")||_(o,"name",e),(a=n(o)).source||(a.source=r.join("string"==typeof e?e:""))),t!==i?(u?!f&&t[e]&&(s=!0):delete t[e],s?t[e]=o:_(t,e,o)):s?t[e]=o:A(e,o)})(Function.prototype,"toString",(function(){return"function"==typeof this&&e(this).source||V(this)}))})),at=i,ut=function(t){return"function"==typeof t?t:void 0},st=function(t,e){return arguments.length<2?ut(at[t])||ut(i[t]):at[t]&&at[t][e]||i[t]&&i[t][e]},ft=Math.ceil,lt=Math.floor,ht=function(t){return isNaN(t=+t)?0:(t>0?lt:ft)(t)},pt=Math.min,dt=function(t){return t>0?pt(ht(t),9007199254740991):0},vt=Math.max,gt=Math.min,yt=function(t){return function(e,n,r){var o,i=y(e),c=dt(i.length),a=function(t,e){var n=ht(t);return n<0?vt(n+e,0):gt(n,e)}(r,c);if(t&&n!=n){for(;c>a;)if((o=i[a++])!=o)return!0}else for(;c>a;a++)if((t||a in i)&&i[a]===n)return t||a||0;return!t&&-1}},mt={includes:yt(!0),indexOf:yt(!1)}.indexOf,bt=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"].concat("length","prototype"),wt={f:Object.getOwnPropertyNames||function(t){return function(t,e){var n,r=y(t),o=0,i=[];for(n in r)!j(Y,n)&&j(r,n)&&i.push(n);for(;e.length>o;)j(r,n=e[o++])&&(~mt(i,n)||i.push(n));return i}(t,bt)}},St={f:Object.getOwnPropertySymbols},jt=st("Reflect","ownKeys")||function(t){var e=wt.f(M(t)),n=St.f;return n?e.concat(n(t)):e},Ot=function(t,e){for(var n=jt(e),r=C.f,o=P.f,i=0;i<n.length;i++){var c=n[i];j(t,c)||r(t,c,o(e,c))}},Et=/#|\.prototype\./,kt=function(t,e){var n=Lt[Tt(t)];return n==Mt||n!=Pt&&("function"==typeof e?c(e):!!e)},Tt=kt.normalize=function(t){return String(t).replace(Et,".").toLowerCase()},Lt=kt.data={},Pt=kt.NATIVE="N",Mt=kt.POLYFILL="P",xt=kt,Ct=P.f,_t=function(t,e){var n,r,o,c,a,u=t.target,s=t.global,f=t.stat;if(n=s?i:f?i[u]||A(u,{}):(i[u]||{}).prototype)for(r in e){if(c=e[r],o=t.noTargetGet?(a=Ct(n,r))&&a.value:n[r],!xt(s?r:u+(f?".":"#")+r,t.forced)&&void 0!==o){if(typeof c==typeof o)continue;Ot(c,o)}(t.sham||o&&o.sham)&&_(c,"sham",!0),ct(n,r,c,t)}},At=Array.isArray||function(t){return"Array"==p(t)},It=function(t,e,n){var r=b(e);r in t?C.f(t,r,l(0,n)):t[r]=n},Nt=st("navigator","userAgent")||"",Rt=i.process,Dt=Rt&&Rt.versions,Ft=Dt&&Dt.v8;Ft?ot=(rt=Ft.split("."))[0]<4?1:rt[0]+rt[1]:Nt&&(!(rt=Nt.match(/Edge\/(\d+)/))||rt[1]>=74)&&(rt=Nt.match(/Chrome\/(\d+)/))&&(ot=rt[1]);var Gt,Kt=ot&&+ot,Vt=!!Object.getOwnPropertySymbols&&!c((function(){var t=Symbol();return!String(t)||!(Object(t)instanceof Symbol)||!Symbol.sham&&Kt&&Kt<41})),Bt=Vt&&!Symbol.sham&&"symbol"==typeof Symbol.iterator,zt=U("wks"),Ut=i.Symbol,Ht=Bt?Ut:Ut&&Ut.withoutSetter||W,qt=function(t){return j(zt,t)&&(Vt||"string"==typeof zt[t])||(Vt&&j(Ut,t)?zt[t]=Ut[t]:zt[t]=Ht("Symbol."+t)),zt[t]},Wt=qt("species"),Jt=function(t,e){var n;return At(t)&&("function"!=typeof(n=t.constructor)||n!==Array&&!At(n.prototype)?m(n)&&null===(n=n[Wt])&&(n=void 0):n=void 0),new(void 0===n?Array:n)(0===e?0:e)},Yt=qt("species"),Qt=qt("isConcatSpreadable"),Xt=9007199254740991,Zt="Maximum allowed index exceeded",$t=Kt>=51||!c((function(){var t=[];return t[Qt]=!1,t.concat()[0]!==t})),te=(Gt="concat",Kt>=51||!c((function(){var t=[];return(t.constructor={})[Yt]=function(){return{foo:1}},1!==t[Gt](Boolean).foo}))),ee=function(t){if(!m(t))return!1;var e=t[Qt];return void 0!==e?!!e:At(t)};_t({target:"Array",proto:!0,forced:!$t||!te},{concat:function(t){var e,n,r,o,i,c=w(this),a=Jt(c,0),u=0;for(e=-1,r=arguments.length;e<r;e++)if(ee(i=-1===e?c:arguments[e])){if(u+(o=dt(i.length))>Xt)throw TypeError(Zt);for(n=0;n<o;n++,u++)n in i&&It(a,u,i[n])}else{if(u>=Xt)throw TypeError(Zt);It(a,u++,i)}return a.length=u,a}});var ne=function(t,e){var n=[][t];return!!n&&c((function(){n.call(null,e||function(){throw 1},1)}))},re=[].join,oe=v!=Object,ie=ne("join",",");_t({target:"Array",proto:!0,forced:oe||!ie},{join:function(t){return re.call(y(this),void 0===t?",":t)}});var ce={};ce[qt("toStringTag")]="z";var ae="[object z]"===String(ce),ue=qt("toStringTag"),se="Arguments"==p(function(){return arguments}()),fe=ae?p:function(t){var e,n,r;return void 0===t?"Undefined":null===t?"Null":"string"==typeof(n=function(t,e){try{return t[e]}catch(t){}}(e=Object(t),ue))?n:se?p(e):"Object"==(r=p(e))&&"function"==typeof e.callee?"Arguments":r},le=ae?{}.toString:function(){return"[object "+fe(this)+"]"};ae||ct(Object.prototype,"toString",le,{unsafe:!0});var he=i.Promise,pe=Object.setPrototypeOf||("__proto__"in{}?function(){var t,e=!1,n={};try{(t=Object.getOwnPropertyDescriptor(Object.prototype,"__proto__").set).call(n,[]),e=n instanceof Array}catch(t){}return function(n,r){return M(n),function(t){if(!m(t)&&null!==t)throw TypeError("Can't set "+String(t)+" as a prototype")}(r),e?t.call(n,r):n.__proto__=r,n}}():void 0),de=C.f,ve=qt("toStringTag"),ge=qt("species"),ye=function(t){if("function"!=typeof t)throw TypeError(String(t)+" is not a function");return t},me={},be=qt("iterator"),we=Array.prototype,Se=function(t,e,n){if(ye(t),void 0===e)return t;switch(n){case 0:return function(){return t.call(e)};case 1:return function(n){return t.call(e,n)};case 2:return function(n,r){return t.call(e,n,r)};case 3:return function(n,r,o){return t.call(e,n,r,o)}}return function(){return t.apply(e,arguments)}},je=qt("iterator"),Oe=function(t){var e=t.return;if(void 0!==e)return M(e.call(t)).value},Ee=function(t,e){this.stopped=t,this.result=e},ke=function(t,e,n){var r,o,i,c,a,u,s,f,l=n&&n.that,h=!(!n||!n.AS_ENTRIES),p=!(!n||!n.IS_ITERATOR),d=!(!n||!n.INTERRUPTED),v=Se(e,l,1+h+d),g=function(t){return r&&Oe(r),new Ee(!0,t)},y=function(t){return h?(M(t),d?v(t[0],t[1],g):v(t[0],t[1])):d?v(t,g):v(t)};if(p)r=t;else{if("function"!=typeof(o=function(t){if(null!=t)return t[je]||t["@@iterator"]||me[fe(t)]}(t)))throw TypeError("Target is not iterable");if(void 0!==(f=o)&&(me.Array===f||we[be]===f)){for(i=0,c=dt(t.length);c>i;i++)if((a=y(t[i]))&&a instanceof Ee)return a;return new Ee(!1)}r=o.call(t)}for(u=r.next;!(s=u.call(r)).done;){try{a=y(s.value)}catch(t){throw Oe(r),t}if("object"==typeof a&&a&&a instanceof Ee)return a}return new Ee(!1)},Te=qt("iterator"),Le=!1;try{var Pe=0,Me={next:function(){return{done:!!Pe++}},return:function(){Le=!0}};Me[Te]=function(){return this},Array.from(Me,(function(){throw 2}))}catch(t){}var xe,Ce,_e,Ae=qt("species"),Ie=st("document","documentElement"),Ne=/(?:iphone|ipod|ipad).*applewebkit/i.test(Nt),Re="process"==p(i.process),De=i.location,Fe=i.setImmediate,Ge=i.clearImmediate,Ke=i.process,Ve=i.MessageChannel,Be=i.Dispatch,ze=0,Ue={},He="onreadystatechange",qe=function(t){if(Ue.hasOwnProperty(t)){var e=Ue[t];delete Ue[t],e()}},We=function(t){return function(){qe(t)}},Je=function(t){qe(t.data)},Ye=function(t){i.postMessage(t+"",De.protocol+"//"+De.host)};Fe&&Ge||(Fe=function(t){for(var e=[],n=1;arguments.length>n;)e.push(arguments[n++]);return Ue[++ze]=function(){("function"==typeof t?t:Function(t)).apply(void 0,e)},xe(ze),ze},Ge=function(t){delete Ue[t]},Re?xe=function(t){Ke.nextTick(We(t))}:Be&&Be.now?xe=function(t){Be.now(We(t))}:Ve&&!Ne?(_e=(Ce=new Ve).port2,Ce.port1.onmessage=Je,xe=Se(_e.postMessage,_e,1)):i.addEventListener&&"function"==typeof postMessage&&!i.importScripts&&De&&"file:"!==De.protocol&&!c(Ye)?(xe=Ye,i.addEventListener("message",Je,!1)):xe=He in k("script")?function(t){Ie.appendChild(k("script")).onreadystatechange=function(){Ie.removeChild(this),qe(t)}}:function(t){setTimeout(We(t),0)});var Qe,Xe,Ze,$e,tn,en,nn,rn,on={set:Fe,clear:Ge},cn=/web0s(?!.*chrome)/i.test(Nt),an=P.f,un=on.set,sn=i.MutationObserver||i.WebKitMutationObserver,fn=i.document,ln=i.process,hn=i.Promise,pn=an(i,"queueMicrotask"),dn=pn&&pn.value;dn||(Qe=function(){var t,e;for(Re&&(t=ln.domain)&&t.exit();Xe;){e=Xe.fn,Xe=Xe.next;try{e()}catch(t){throw Xe?$e():Ze=void 0,t}}Ze=void 0,t&&t.enter()},Ne||Re||cn||!sn||!fn?hn&&hn.resolve?((nn=hn.resolve(void 0)).constructor=hn,rn=nn.then,$e=function(){rn.call(nn,Qe)}):$e=Re?function(){ln.nextTick(Qe)}:function(){un.call(i,Qe)}:(tn=!0,en=fn.createTextNode(""),new sn(Qe).observe(en,{characterData:!0}),$e=function(){en.data=tn=!tn}));var vn,gn,yn,mn,bn,wn,Sn,jn=dn||function(t){var e={fn:t,next:void 0};Ze&&(Ze.next=e),Xe||(Xe=e,$e()),Ze=e},On=function(t){var e,n;this.promise=new t((function(t,r){if(void 0!==e||void 0!==n)throw TypeError("Bad Promise constructor");e=t,n=r})),this.resolve=ye(e),this.reject=ye(n)},En={f:function(t){return new On(t)}},kn=function(t){try{return{error:!1,value:t()}}catch(t){return{error:!0,value:t}}},Tn="object"==typeof window,Ln=on.set,Pn=qt("species"),Mn="Promise",xn=it.get,Cn=it.set,_n=it.getterFor(Mn),An=he&&he.prototype,In=he,Nn=An,Rn=i.TypeError,Dn=i.document,Fn=i.process,Gn=En.f,Kn=Gn,Vn=!!(Dn&&Dn.createEvent&&i.dispatchEvent),Bn="function"==typeof PromiseRejectionEvent,zn="unhandledrejection",Un=!1,Hn=xt(Mn,(function(){var t=V(In)!==String(In);if(!t&&66===Kt)return!0;if(Kt>=51&&/native code/.test(In))return!1;var e=new In((function(t){t(1)})),n=function(t){t((function(){}),(function(){}))};return(e.constructor={})[Pn]=n,!(Un=e.then((function(){}))instanceof n)||!t&&Tn&&!Bn})),qn=Hn||!function(t,e){if(!e&&!Le)return!1;var n=!1;try{var r={};r[Te]=function(){return{next:function(){return{done:n=!0}}}},t(r)}catch(t){}return n}((function(t){In.all(t).catch((function(){}))})),Wn=function(t){var e;return!(!m(t)||"function"!=typeof(e=t.then))&&e},Jn=function(t,e){if(!t.notified){t.notified=!0;var n=t.reactions;jn((function(){for(var r=t.value,o=1==t.state,i=0;n.length>i;){var c,a,u,s=n[i++],f=o?s.ok:s.fail,l=s.resolve,h=s.reject,p=s.domain;try{f?(o||(2===t.rejection&&Zn(t),t.rejection=1),!0===f?c=r:(p&&p.enter(),c=f(r),p&&(p.exit(),u=!0)),c===s.promise?h(Rn("Promise-chain cycle")):(a=Wn(c))?a.call(c,l,h):l(c)):h(r)}catch(t){p&&!u&&p.exit(),h(t)}}t.reactions=[],t.notified=!1,e&&!t.rejection&&Qn(t)}))}},Yn=function(t,e,n){var r,o;Vn?((r=Dn.createEvent("Event")).promise=e,r.reason=n,r.initEvent(t,!1,!0),i.dispatchEvent(r)):r={promise:e,reason:n},!Bn&&(o=i["on"+t])?o(r):t===zn&&function(t,e){var n=i.console;n&&n.error&&(1===arguments.length?n.error(t):n.error(t,e))}("Unhandled promise rejection",n)},Qn=function(t){Ln.call(i,(function(){var e,n=t.facade,r=t.value;if(Xn(t)&&(e=kn((function(){Re?Fn.emit("unhandledRejection",r,n):Yn(zn,n,r)})),t.rejection=Re||Xn(t)?2:1,e.error))throw e.value}))},Xn=function(t){return 1!==t.rejection&&!t.parent},Zn=function(t){Ln.call(i,(function(){var e=t.facade;Re?Fn.emit("rejectionHandled",e):Yn("rejectionhandled",e,t.value)}))},$n=function(t,e,n){return function(r){t(e,r,n)}},tr=function(t,e,n){t.done||(t.done=!0,n&&(t=n),t.value=e,t.state=2,Jn(t,!0))},er=function(t,e,n){if(!t.done){t.done=!0,n&&(t=n);try{if(t.facade===e)throw Rn("Promise can't be resolved itself");var r=Wn(e);r?jn((function(){var n={done:!1};try{r.call(e,$n(er,n,t),$n(tr,n,t))}catch(e){tr(n,e,t)}})):(t.value=e,t.state=1,Jn(t,!1))}catch(e){tr({done:!1},e,t)}}};if(Hn&&(Nn=(In=function(t){!function(t,e,n){if(!(t instanceof e))throw TypeError("Incorrect "+(n?n+" ":"")+"invocation")}(this,In,Mn),ye(t),vn.call(this);var e=xn(this);try{t($n(er,e),$n(tr,e))}catch(t){tr(e,t)}}).prototype,(vn=function(t){Cn(this,{type:Mn,done:!1,notified:!1,parent:!1,reactions:[],rejection:!1,state:0,value:void 0})}).prototype=function(t,e,n){for(var r in e)ct(t,r,e[r],n);return t}(Nn,{then:function(t,e){var n,r,o,i=_n(this),c=Gn((n=In,void 0===(o=M(this).constructor)||null==(r=M(o)[Ae])?n:ye(r)));return c.ok="function"!=typeof t||t,c.fail="function"==typeof e&&e,c.domain=Re?Fn.domain:void 0,i.parent=!0,i.reactions.push(c),0!=i.state&&Jn(i,!1),c.promise},catch:function(t){return this.then(void 0,t)}}),gn=function(){var t=new vn,e=xn(t);this.promise=t,this.resolve=$n(er,e),this.reject=$n(tr,e)},En.f=Gn=function(t){return t===In||t===yn?new gn(t):Kn(t)},"function"==typeof he&&An!==Object.prototype)){mn=An.then,Un||(ct(An,"then",(function(t,e){var n=this;return new In((function(t,e){mn.call(n,t,e)})).then(t,e)}),{unsafe:!0}),ct(An,"catch",Nn.catch,{unsafe:!0}));try{delete An.constructor}catch(t){}pe&&pe(An,Nn)}_t({global:!0,wrap:!0,forced:Hn},{Promise:In}),wn=Mn,Sn=!1,(bn=In)&&!j(bn=Sn?bn:bn.prototype,ve)&&de(bn,ve,{configurable:!0,value:wn}),function(t){var e=st(t),n=C.f;a&&e&&!e[ge]&&n(e,ge,{configurable:!0,get:function(){return this}})}(Mn),yn=st(Mn),_t({target:Mn,stat:!0,forced:Hn},{reject:function(t){var e=Gn(this);return e.reject.call(void 0,t),e.promise}}),_t({target:Mn,stat:!0,forced:Hn},{resolve:function(t){return function(t,e){if(M(t),m(e)&&e.constructor===t)return e;var n=En.f(t);return(0,n.resolve)(e),n.promise}(this,t)}}),_t({target:Mn,stat:!0,forced:qn},{all:function(t){var e=this,n=Gn(e),r=n.resolve,o=n.reject,i=kn((function(){var n=ye(e.resolve),i=[],c=0,a=1;ke(t,(function(t){var u=c++,s=!1;i.push(void 0),a++,n.call(e,t).then((function(t){s||(s=!0,i[u]=t,--a||r(i))}),o)})),--a||r(i)}));return i.error&&o(i.value),n.promise},race:function(t){var e=this,n=Gn(e),r=n.reject,o=kn((function(){var o=ye(e.resolve);ke(t,(function(t){o.call(e,t).then(n.resolve,r)}))}));return o.error&&r(o.value),n.promise}});var nr=[].push,rr=function(t){var e=1==t,n=2==t,r=3==t,o=4==t,i=6==t,c=7==t,a=5==t||i;return function(u,s,f,l){for(var h,p,d=w(u),g=v(d),y=Se(s,f,3),m=dt(g.length),b=0,S=l||Jt,j=e?S(u,m):n||c?S(u,0):void 0;m>b;b++)if((a||b in g)&&(p=y(h=g[b],b,d),t))if(e)j[b]=p;else if(p)switch(t){case 3:return!0;case 5:return h;case 6:return b;case 2:nr.call(j,h)}else switch(t){case 4:return!1;case 7:nr.call(j,h)}return i?-1:r||o?o:j}},or={forEach:rr(0),map:rr(1),filter:rr(2),some:rr(3),every:rr(4),find:rr(5),findIndex:rr(6),filterOut:rr(7)}.forEach,ir=ne("forEach")?[].forEach:function(t){return or(this,t,arguments.length>1?arguments[1]:void 0)};for(var cr in{CSSRuleList:0,CSSStyleDeclaration:0,CSSValueList:0,ClientRectList:0,DOMRectList:0,DOMStringList:0,DOMTokenList:1,DataTransferItemList:0,FileList:0,HTMLAllCollection:0,HTMLCollection:0,HTMLFormElement:0,HTMLSelectElement:0,MediaList:0,MimeTypeArray:0,NamedNodeMap:0,NodeList:1,PaintRequestList:0,Plugin:0,PluginArray:0,SVGLengthList:0,SVGNumberList:0,SVGPathSegList:0,SVGPointList:0,SVGStringList:0,SVGTransformList:0,SourceBufferList:0,StyleSheetList:0,TextTrackCueList:0,TextTrackList:0,TouchList:0}){var ar=i[cr],ur=ar&&ar.prototype;if(ur&&ur.forEach!==ir)try{_(ur,"forEach",ir)}catch(t){ur.forEach=ir}}var sr="__googleMapsScriptId",fr=function(){function t(e){var n=e.apiKey,r=e.channel,o=e.client,i=e.id,c=void 0===i?sr:i,a=e.libraries,u=void 0===a?[]:a,s=e.language,f=e.region,l=e.version,h=e.mapIds,p=e.nonce,d=e.retries,v=void 0===d?3:d,g=e.url,y=void 0===g?"https://maps.googleapis.com/maps/api/js":g;if(function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.CALLBACK="__googleMapsCallback",this.callbacks=[],this.done=!1,this.loading=!1,this.errors=[],this.version=l,this.apiKey=n,this.channel=r,this.client=o,this.id=c||sr,this.libraries=u,this.language=s,this.region=f,this.mapIds=h,this.nonce=p,this.retries=v,this.url=y,t.instance){if(!function t(e,n){if(e===n)return!0;if(e&&n&&"object"==typeof e&&"object"==typeof n){if(e.constructor!==n.constructor)return!1;var r,o,i;if(Array.isArray(e)){if((r=e.length)!=n.length)return!1;for(o=r;0!=o--;)if(!t(e[o],n[o]))return!1;return!0}if(e.constructor===RegExp)return e.source===n.source&&e.flags===n.flags;if(e.valueOf!==Object.prototype.valueOf)return e.valueOf()===n.valueOf();if(e.toString!==Object.prototype.toString)return e.toString()===n.toString();if((r=(i=Object.keys(e)).length)!==Object.keys(n).length)return!1;for(o=r;0!=o--;)if(!Object.prototype.hasOwnProperty.call(n,i[o]))return!1;for(o=r;0!=o--;){var c=i[o];if(!t(e[c],n[c]))return!1}return!0}return e!=e&&n!=n}(this.options,t.instance.options))throw new Error("Loader must not be called again with different options. ".concat(JSON.stringify(this.options)," !== ").concat(JSON.stringify(t.instance.options)));return t.instance}t.instance=this}var n,r,o;return n=t,(r=[{key:"options",get:function(){return{version:this.version,apiKey:this.apiKey,channel:this.channel,client:this.client,id:this.id,libraries:this.libraries,language:this.language,region:this.region,mapIds:this.mapIds,nonce:this.nonce,url:this.url}}},{key:"failed",get:function(){return this.done&&!this.loading&&this.errors.length>=this.retries+1}},{key:"createUrl",value:function(){var t=this.url;return t+="?callback=".concat(this.CALLBACK),this.apiKey&&(t+="&key=".concat(this.apiKey)),this.channel&&(t+="&channel=".concat(this.channel)),this.client&&(t+="&client=".concat(this.client)),this.libraries.length>0&&(t+="&libraries=".concat(this.libraries.join(","))),this.language&&(t+="&language=".concat(this.language)),this.region&&(t+="®ion=".concat(this.region)),this.version&&(t+="&v=".concat(this.version)),this.mapIds&&(t+="&map_ids=".concat(this.mapIds.join(","))),t}},{key:"load",value:function(){return this.loadPromise()}},{key:"loadPromise",value:function(){var t=this;return new Promise((function(e,n){t.loadCallback((function(t){t?n(t):e(window.google)}))}))}},{key:"loadCallback",value:function(t){this.callbacks.push(t),this.execute()}},{key:"setScript",value:function(){if(document.getElementById(this.id))this.callback();else{var t=this.createUrl(),e=document.createElement("script");e.id=this.id,e.type="text/javascript",e.src=t,e.onerror=this.loadErrorCallback.bind(this),e.defer=!0,e.async=!0,this.nonce&&(e.nonce=this.nonce),document.head.appendChild(e)}}},{key:"deleteScript",value:function(){var t=document.getElementById(this.id);t&&t.remove()}},{key:"reset",value:function(){this.deleteScript(),this.done=!1,this.loading=!1,this.errors=[],this.onerrorEvent=null}},{key:"resetIfRetryingFailed",value:function(){this.failed&&this.reset()}},{key:"loadErrorCallback",value:function(t){var e=this;if(this.errors.push(t),this.errors.length<=this.retries){var n=this.errors.length*Math.pow(2,this.errors.length);console.log("Failed to load Google Maps script, retrying in ".concat(n," ms.")),setTimeout((function(){e.deleteScript(),e.setScript()}),n)}else this.onerrorEvent=t,this.callback()}},{key:"setCallback",value:function(){window.__googleMapsCallback=this.callback.bind(this)}},{key:"callback",value:function(){var t=this;this.done=!0,this.loading=!1,this.callbacks.forEach((function(e){e(t.onerrorEvent)})),this.callbacks=[]}},{key:"execute",value:function(){if(this.resetIfRetryingFailed(),this.done)this.callback();else{if(window.google&&window.google.maps&&window.google.maps.version)return console.warn("Google Maps already loaded outside @googlemaps/js-api-loader.This may result in undesirable behavior as options and script parameters may not match."),void this.callback();this.loading||(this.loading=!0,this.setCallback(),this.setScript())}}}])&&e(n.prototype,r),o&&e(n,o),t}();return t.DEFAULT_ID=sr,t.Loader=fr,Object.defineProperty(t,"__esModule",{value:!0}),t}({}); dist/manifest.php 0000644 00000001516 15172727763 0010052 0 ustar 00 <?php
/* THIS IS A GENERATED FILE. DO NOT EDIT DIRECTLY. */
$manifestJson = '{
"src/assets/scss/business-info.scss": {
"file": "css/business-info.DL1L3NWa.css",
"src": "src/assets/scss/business-info.scss",
"isEntry": true
},
"src/assets/scss/location-map.scss": {
"file": "css/location-map.DZ9K1ruc.css",
"src": "src/assets/scss/location-map.scss",
"isEntry": true
},
"src/assets/scss/opening-hours.scss": {
"file": "css/opening-hours.Bdv_HHb0.css",
"src": "src/assets/scss/opening-hours.scss",
"isEntry": true
},
"src/js-api-loader.js": {
"file": "js/js-api-loader.liRm3N-P.js",
"name": "js-api-loader",
"src": "src/js-api-loader.js",
"isEntry": true
},
"src/map.js": {
"file": "js/map.DRPxR061.js",
"name": "map",
"src": "src/map.js",
"isEntry": true
}
}'; dist/css/location-map.DZ9K1ruc.css 0000644 00000000335 15172727763 0012731 0 ustar 00 .aioseo-location-map .d-flex{display:flex}.aioseo-location-map .col{flex:1}.aioseo-location-map .col-auto{flex:0 0 auto}.aioseo-location-map .aioseo-local-map .marker-info-window .name{font-weight:700;padding-bottom:3px}
dist/css/opening-hours.Bdv_HHb0.css 0000644 00000001220 15172727763 0013135 0 ustar 00 .aioseo-opening-hours .d-flex{display:flex}.aioseo-opening-hours .col{flex:1}.aioseo-opening-hours .col-auto{flex:0 0 auto}.aioseo-opening-hours .aioseo-opening-hours-icon{display:inline-block}[dir=ltr] .aioseo-opening-hours .aioseo-opening-hours-icon{margin-right:17px}[dir=rtl] .aioseo-opening-hours .aioseo-opening-hours-icon{margin-left:17px}.aioseo-opening-hours .aioseo-opening-hours-table{border:transparent;border-collapse:collapse;border-spacing:0;margin:10px -.5em;max-width:100%;overflow:hidden;width:100%}.aioseo-opening-hours .aioseo-opening-hours-table th,.aioseo-opening-hours .aioseo-opening-hours-table td{border:transparent;padding:.5em}
dist/css/business-info.DL1L3NWa.css 0000644 00000001305 15172727764 0013002 0 ustar 00 .aioseo-location-box,.aioseo-location-box .d-flex{display:flex}.aioseo-location-box>[class*=col]{padding:0 15px 20px}.aioseo-location-box .col{flex:1}.aioseo-location-box .col-auto{flex:0 0 auto}.aioseo-location-box .label{opacity:.5}[dir=ltr] .aioseo-location-box .icon{padding-right:17px}[dir=rtl] .aioseo-location-box .icon{padding-left:17px}.aioseo-location-box .aioseo-name-details{padding-bottom:10px}.aioseo-location-box .aioseo-address-details{padding-bottom:26px}.aioseo-location-box .aioseo-contact-details>div{padding-bottom:20px}.aioseo-location-box.hide-label .label,.aioseo-location-box.hide-icon .icon{display:none}.aioseo-local-business-info-widget .aioseo-location-box{flex-direction:column}
app/Admin/Location.php 0000644 00000017051 15172727764 0010663 0 ustar 00 <?php
namespace AIOSEO\Plugin\Addon\LocalBusiness\Admin;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* The Location class.
*
* @since 1.1.0
*/
class Location {
/**
* Class constructor.
*
* @since 1.1.0
*/
public function __construct() {
add_action( 'init', [ $this, 'register' ] );
}
/**
* Returns the post type name.
*
* @since 1.1.0
*
* @return string The post name.
*/
public function getName() {
return apply_filters( 'aioseo_local_business_post_type_name', 'aioseo-location' );
}
/**
* Returns the current slug for the post type.
*
* @since 1.1.0
*
* @return string The post rewrite slug.
*/
public function getSlug() {
$useCustomSlug = aioseo()->options->localBusiness->locations->general->useCustomSlug;
$customSlugOption = aioseo()->options->localBusiness->locations->general->customSlug ?: '';
$customSlug = ( true === $useCustomSlug && 0 < strlen( $customSlugOption ) )
? $customSlugOption
: $this->getDefaultSlug();
$customSlug = apply_filters( 'aioseo_local_business_post_type_slug', $customSlug );
return $customSlug;
}
/**
* Returns the default slug for the post type.
*
* @since 1.1.0
*
* @return string The default rewrite slug.
*/
public function getDefaultSlug() {
return 'location';
}
/**
* Returns the single label for the post type.
*
* @since 1.1.0
*
* @return string The post single label.
*/
public function getSingleLabel() {
$singleLabelOption = aioseo()->options->localBusiness->locations->general->singleLabel ?: '';
$singleLabel = ( 0 < strlen( $singleLabelOption ) ) ? $singleLabelOption : __( 'Location', 'aioseo-local-business' );
$singleLabel = apply_filters( 'aioseo_local_business_post_type_single_label', $singleLabel );
return $singleLabel;
}
/**
* Returns the plural label for the post type.
*
* @since 1.1.0
*
* @return string The post plural label.
*/
public function getPluralLabel() {
$pluralLabelOption = aioseo()->options->localBusiness->locations->general->pluralLabel ?: '';
$pluralLabel = ( 0 < strlen( $pluralLabelOption ) ) ? $pluralLabelOption : __( 'Locations', 'aioseo-local-business' );
$pluralLabel = apply_filters( 'aioseo_local_business_post_type_plural_label', $pluralLabel );
return $pluralLabel;
}
/**
* Returns current permalink structure for this post type.
*
* @since 1.1.0
*
* @return string The loaded permastruct or a default if not enabled yet.
*/
public function getPermaStructure() {
return aioseoLocalBusiness()->helpers->getPermaStructure( $this->getName(), $this->getSlug() );
}
/**
* Returns edit link for this post type.
*
* @since 1.1.0
*
* @return false|string The main post type edit link.
*/
public function getEditLink() {
return admin_url( 'edit.php?post_type=' . $this->getName() );
}
/**
* Returns this post type capabilites.
*
* @since 1.1.0
*
* @return array An array of mapped capabilities.
*/
public function getCapabilities() {
return [
'edit_post' => 'edit_aioseo_location',
'edit_posts' => 'edit_aioseo_locations',
'edit_others_posts' => 'edit_other_aioseo_locations',
'publish_posts' => 'publish_aioseo_locations',
'read_post' => 'read_aioseo_location',
'read_private_posts' => 'read_private_aioseo_locations',
'delete_post' => 'delete_aioseo_location'
];
}
/**
* Register the post type.
*
* @since 1.1.0
*
* @return void
*/
public function register() {
if ( ! aioseo()->options->localBusiness->locations->general->multiple ) {
return;
}
$labels = [
'name' => $this->getPluralLabel(),
'singular_name' => $this->getSingleLabel(),
// Translators: 1 - Singular post type name.
'archives' => sprintf( _x( '%1$s Archives', 'Post Type', 'aioseo-local-business' ), $this->getSingleLabel() ),
// Translators: 1 - Singular post type name.
'attributes' => sprintf( _x( '%1$s Attributes', 'Post Type', 'aioseo-local-business' ), $this->getSingleLabel() ),
// Translators: 1 - Singular post type name.
'parent_item_colon' => sprintf( _x( 'Parent %1$s:', 'Post Type', 'aioseo-local-business' ), $this->getSingleLabel() ),
// Translators: 1 - Plural post type name.
'all_items' => sprintf( _x( 'All %1$s', 'Post Type', 'aioseo-local-business' ), $this->getPluralLabel() ),
// Translators: 1 - Singular post type name.
'add_new' => sprintf( _x( 'Add New %1$s', 'Post Type', 'aioseo-local-business' ), $this->getSingleLabel() ),
// Translators: 1 - Singular post type name.
'add_new_item' => sprintf( _x( 'Add New %1$s', 'Post Type', 'aioseo-local-business' ), $this->getSingleLabel() ),
// Translators: 1 - Singular post type name.
'new_item' => sprintf( _x( 'New %1$s', 'Post Type', 'aioseo-local-business' ), $this->getSingleLabel() ),
// Translators: 1 - Singular post type name.
'edit_item' => sprintf( _x( 'Edit %1$s', 'Post Type', 'aioseo-local-business' ), $this->getSingleLabel() ),
// Translators: 1 - Singular post type name.
'update_item' => sprintf( _x( 'Update %1$s', 'Post Type', 'aioseo-local-business' ), $this->getSingleLabel() ),
// Translators: 1 - Singular or plural post type name.
'view_item' => sprintf( _x( 'View %1$s', 'Post Type', 'aioseo-local-business' ), $this->getSingleLabel() ),
// Translators: 1 - Singular or plural post type name.
'view_items' => sprintf( _x( 'View %1$s', 'Post Type', 'aioseo-local-business' ), $this->getPluralLabel() ),
// Translators: 1 - Singular post type name.
'search_items' => sprintf( _x( 'Search %1$s', 'Post Type', 'aioseo-local-business' ), $this->getSingleLabel() ),
// Translators: 1 - Singular post type name.
'insert_into_item' => sprintf( _x( 'Insert into %1$s', 'Post Type', 'aioseo-local-business' ), $this->getSingleLabel() ),
// Translators: 1 - Singular post type name.
'uploaded_to_this_item' => sprintf( _x( 'Uploaded to this %1$s', 'Post Type', 'aioseo-local-business' ), $this->getSingleLabel() ),
// Translators: 1 - Plural post type name.
'items_list' => sprintf( _x( '%1$s list', 'Post Type', 'aioseo-local-business' ), $this->getPluralLabel() ),
// Translators: 1 - Plural post type name.
'items_list_navigation' => sprintf( _x( '%1$s list navigation', 'Post Type', 'aioseo-local-business' ), $this->getPluralLabel() ),
// Translators: 1 - Plural post type name.
'filter_items_list' => sprintf( _x( 'Filter %1$s list', 'Post Type', 'aioseo-local-business' ), $this->getPluralLabel() ),
];
$postType = [
'labels' => $labels,
'description' => sprintf(
// Translators: 1 - The plugin name ("All in One SEO").
__( '%1$s uses these locations to generate Local Business schema markup.', 'aioseo-local-business' ),
AIOSEO_PLUGIN_NAME
),
'public' => true,
'rewrite' => [
'slug' => $this->getSlug(),
],
'pages' => false,
'menu_icon' => 'dashicons-location',
'show_in_rest' => true,
'capabilities' => $this->getCapabilities(),
'map_meta_cap' => true,
'supports' => [ 'title', 'editor', 'thumbnail' ]
];
$postType = apply_filters( 'aioseo_local_business_post_type', $postType );
if ( ! in_array( $this->getName(), get_post_types(), true ) ) {
aioseo()->options->flushRewriteRules();
}
register_post_type(
$this->getName(),
$postType
);
register_rest_field( $this->getName(), 'maps', [
'get_callback' => [ aioseoLocalBusiness()->maps, 'restMapInfo' ]
] );
}
} app/Admin/Admin.php 0000644 00000002542 15172727764 0010142 0 ustar 00 <?php
namespace AIOSEO\Plugin\Addon\LocalBusiness\Admin;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
use AIOSEO\Plugin\Common\Admin as CommonAdmin;
/**
* The Admin class.
*
* @since 1.1.0
*/
class Admin extends CommonAdmin\Admin {
/**
* Class constructor.
*
* @since 1.0.0
*/
public function __construct() {
if ( is_admin() ) {
add_action( 'add_meta_boxes', [ $this, 'addMetabox' ] );
}
}
/**
* Adds a meta box to the page/posts screens.
*
* @since 1.1.0
*
* @return void
*/
public function addMetabox() {
if ( ! aioseo()->access->hasCapability( 'aioseo_page_local_seo_settings' ) ) {
return;
}
// Translators: 1 - The plugin short name ("AIOSEO").
$aioseoMetaboxTitle = sprintf( esc_html__( '%1$s Local Business', 'aioseo-local-business' ), AIOSEO_PLUGIN_SHORT_NAME );
add_meta_box(
'aioseo-local-settings',
$aioseoMetaboxTitle,
[ $this, 'renderMetabox' ],
[ aioseoLocalBusiness()->postType->getName() ],
'normal',
'high'
);
}
/**
* Render the on-page settings metabox with the Vue App wrapper.
*
* @since 1.1.0
*
* @return void
*/
public function renderMetabox() {
aioseo()->postSettings->postSettingsHiddenField();
?>
<div id="aioseo-location-settings-metabox">
<?php aioseo()->templates->getTemplate( 'parts/loader.php' ); ?>
</div>
<?php
}
} app/Admin/LocationCategory.php 0000644 00000012343 15172727764 0012360 0 ustar 00 <?php
namespace AIOSEO\Plugin\Addon\LocalBusiness\Admin;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* The Location class.
*
* @since 1.1.0
*/
class LocationCategory {
/**
* Location constructor.
*
* @since 1.1.0
*/
public function __construct() {
add_action( 'init', [ $this, 'register' ] );
}
/**
* Returns the post type name.
*
* @since 1.1.0
*
* @return string The taxonomy name.
*/
public function getName() {
return apply_filters( 'aioseo_local_business_taxonomy_name', 'aioseo-location-category' );
}
/**
* Returns the current slug for the taxonomy.
*
* @since 1.1.0
*
* @return string The taxonomy slug.
*/
public function getSlug() {
$useCustomSlug = aioseo()->options->localBusiness->locations->general->useCustomCategorySlug;
$customSlugOption = aioseo()->options->localBusiness->locations->general->customCategorySlug ?: '';
$customSlug = ( true === $useCustomSlug && 0 < strlen( $customSlugOption ) )
? $customSlugOption
: $this->getDefaultSlug();
$customSlug = apply_filters( 'aioseo_local_business_taxonomy_slug', $customSlug );
return $customSlug;
}
/**
* Returns the default slug for the taxonomy.
*
* @since 1.1.0
*
* @return string The taxonomy default slug.
*/
public function getDefaultSlug() {
return 'locations-category';
}
/**
* Returns current permalink structure for this taxonomy.
*
* @since 1.1.0
*
* @return string The loaded permalink structure or a default if not enabled yet.
*/
public function getPermaStructure() {
return aioseoLocalBusiness()->helpers->getPermaStructure( $this->getName(), $this->getSlug() );
}
/**
* Returns the single label for the taxonomy.
*
* @since 1.1.0
*
* @return string The taxonomy label.
*/
public function getSingleLabel() {
return __( 'Location Category', 'aioseo-local-business' );
}
/**
* Returns the plural label for taxonomy.
*
* @since 1.1.0
*
* @return string The taxonomy plural label.
*/
public function getPluralLabel() {
return __( 'Location Categories', 'aioseo-local-business' );
}
/**
* Returns the post type capabilites.
*
* @since 1.1.0
*
* @return array An array of mapped capabilities.
*/
public function getCapabilities() {
return [
'manage_terms' => 'manage_location_categories',
'edit_terms' => 'edit_location_categories',
'delete_terms' => 'delete_location_categories',
'assign_terms' => 'assign_location_categories'
];
}
/**
* Registers the taxonomy.
*
* @since 1.1.0
*
* @return void
*/
public function register() {
if ( ! aioseo()->options->localBusiness->locations->general->multiple ) {
return;
}
$labels = [
'name' => $this->getPluralLabel(),
'singular_name' => $this->getSingleLabel(),
// Translators: 1 - Plural post type name.
'all_items' => sprintf( _x( 'All %1$s', 'Taxonomy', 'aioseo-local-business' ), $this->getPluralLabel() ),
// Translators: 1 - Singular post type name.
'parent_item' => sprintf( _x( 'Parent %1$s', 'Taxonomy', 'aioseo-local-business' ), $this->getSingleLabel() ),
// Translators: 1 - Singular post type name.
'parent_item_colon' => sprintf( _x( 'Parent %1$s:', 'Taxonomy', 'aioseo-local-business' ), $this->getSingleLabel() ),
// Translators: 1 - Singular post type name.
'add_new_item' => sprintf( _x( 'Add New %1$s', 'Taxonomy', 'aioseo-local-business' ), $this->getSingleLabel() ),
// Translators: 1 - Singular post type name.
'edit_item' => sprintf( _x( 'Edit %1$s', 'Taxonomy', 'aioseo-local-business' ), $this->getSingleLabel() ),
// Translators: 1 - Singular post type name.
'update_item' => sprintf( _x( 'Update %1$s', 'Taxonomy', 'aioseo-local-business' ), $this->getSingleLabel() ),
// Translators: 1 - Singular or plural post type name.
'view_item' => sprintf( _x( 'View %1$s', 'Taxonomy', 'aioseo-local-business' ), $this->getSingleLabel() ),
// Translators: 1 - Singular or plural post type name.
'view_items' => sprintf( _x( 'View %1$s', 'Taxonomy', 'aioseo-local-business' ), $this->getPluralLabel() ),
// Translators: 1 - Plural post type name.
'search_items' => sprintf( _x( 'Search %1$s', 'Taxonomy', 'aioseo-local-business' ), $this->getPluralLabel() ),
// Translators: 1 - Plural post type name.
'no_terms' => sprintf( _x( 'No %1$s', 'Taxonomy', 'aioseo-local-business' ), $this->getPluralLabel() ),
// Translators: 1 - Plural post type name.
'items_list_navigation' => sprintf( _x( '%1$s list navigation', 'Taxonomy', 'aioseo-local-business' ), $this->getPluralLabel() ),
// Translators: 1 - Plural post type name.
'filter_items_list' => sprintf( _x( 'Filter %1$s list', 'Taxonomy', 'aioseo-local-business' ), $this->getPluralLabel() )
];
$taxonomy = [
'labels' => $labels,
'public' => true,
'rewrite' => [
'slug' => $this->getSlug(),
],
'show_in_rest' => true,
'capabilities' => $this->getCapabilities(),
'hierarchical' => true
];
$taxonomy = apply_filters( 'aioseo_local_business_taxonomy', $taxonomy );
register_taxonomy( $this->getName(), aioseoLocalBusiness()->postType->getName(), $taxonomy );
}
} app/Admin/Usage.php 0000644 00000000670 15172727764 0010156 0 ustar 00 <?php
namespace AIOSEO\Plugin\Addon\LocalBusiness\Admin;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Description
*
* @since 1.2.10
*/
class Usage {
/**
* Retrieves the data to send in the usage tracking.
*
* @since 1.2.10
*
* @return array An array of data to send.
*/
public function getData() {
return [
'internalOptions' => aioseoLocalBusiness()->internalOptions->all()
];
}
} app/Widgets/Map.php 0000644 00000015107 15172727765 0010207 0 ustar 00 <?php
namespace AIOSEO\Plugin\Addon\LocalBusiness\Widgets;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* AIOSEO Business Info widget.
*
* @since 1.1.3
*/
class Map extends \WP_Widget {
/**
* The default attributes.
*
* @since 1.2.12
*
* @var array
*/
private $defaults = [];
/**
* Class constructor.
*
* @since 1.1.3
*/
public function __construct() {
// Widget defaults.
$this->defaults = [
'title' => '',
'locationId' => '',
'showLabel' => true,
'showIcon' => true,
'width' => '100%',
'height' => '450px',
'label' => __( 'Our location:', 'aioseo-local-business' )
];
// Widget Slug.
$widgetSlug = 'aioseo-local-map-widget';
// Widget basics.
$widgetOps = [
'classname' => $widgetSlug,
'description' => esc_html__( 'Display a location map.', 'aioseo-local-business' ),
];
// Widget controls.
$controlOps = [
'id_base' => $widgetSlug,
];
// Load widget.
parent::__construct( $widgetSlug, esc_html__( 'AIOSEO Local - Map', 'aioseo-local-business' ), $widgetOps, $controlOps );
}
/**
* Widget callback.
*
* @since 1.1.3
*
* @param array $args Widget args.
* @param array $instance The widget instance options.
* @return void
*/
public function widget( $args, $instance ) {
// Merge with defaults.
$instance = wp_parse_args( (array) $instance, $this->defaults );
echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
// Title.
if ( ! empty( $instance['title'] ) ) {
echo $args['before_title'] . apply_filters( 'widget_title', $instance['title'], $instance, $this->id_base ) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped,Generic.Files.LineLength.MaxExceeded
}
// Location info.
aioseoLocalBusiness()->locations->outputLocationMap( $instance['locationId'], $instance );
echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
/**
* Widget option update.
*
* @since 1.1.3
*
* @param array $newInstance New instance options.
* @param array $oldInstance Old instance options.
* @return array Processed new instance options.
*/
public function update( $newInstance, $oldInstance ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
$newInstance['title'] = wp_strip_all_tags( $newInstance['title'] );
$newInstance['showLabel'] = isset( $newInstance['showLabel'] ) ? '1' : false;
$newInstance['showIcon'] = isset( $newInstance['showIcon'] ) ? '1' : false;
return $newInstance;
}
/**
* Widget options form.
*
* @since 1.1.3
*
* @param array $instance The widget instance options.
* @return void
*/
public function form( $instance ) {
// Merge with defaults.
$instance = wp_parse_args( (array) $instance, $this->defaults );
?>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>">
<?php echo esc_html( __( 'Title:', 'aioseo-local-business' ) ); ?>
</label>
<input
type="text"
id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"
name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>"
value="<?php echo esc_attr( $instance['title'] ); ?>"
class="widefat"
/>
</p>
<?php if ( aioseo()->options->localBusiness->locations->general->multiple ) { ?>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'locationId' ) ); ?>">
<?php esc_html_e( 'Location:', 'aioseo-local-business' ); ?>
</label>
<select class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'locationId' ) ); ?>"
name="<?php echo esc_attr( $this->get_field_name( 'locationId' ) ); ?>">
<?php
$locations = aioseoLocalBusiness()->locations->getLocations( [
'order_by' => 'post_title',
'order' => 'asc'
] );
if ( ! empty( $locations ) ) {
echo '<option value="" selected disabled>' . esc_html__( 'Select your location', 'aioseo-local-business' ) . '</option>';
foreach ( $locations as $location ) {
echo '<option value="' . esc_attr( $location->ID ) . '" ' . selected( $instance['locationId'], $location->ID, false ) . '>' . esc_html( $location->post_title ) . '</option>'; // phpcs:ignore Generic.Files.LineLength.MaxExceeded
}
} else {
echo '<option value="">' . esc_html__( 'No locations available', 'aioseo-local-business' ) . '</option>';
}
?>
</select>
</p>
<?php } ?>
<p>
<input type="checkbox" id="<?php echo esc_attr( $this->get_field_id( 'showLabel' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'showLabel' ) ); ?>" <?php checked( '1', $instance['showLabel'] ); ?>> <?php // phpcs:ignore Generic.Files.LineLength.MaxExceeded ?>
<label for="<?php echo esc_attr( $this->get_field_id( 'showLabel' ) ); ?>">
<?php esc_html_e( 'Show label', 'aioseo-local-business' ); ?>
</label>
</p>
<p>
<input type="checkbox" id="<?php echo esc_attr( $this->get_field_id( 'showIcon' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'showIcon' ) ); ?>" <?php checked( '1', $instance['showIcon'] ); ?>> <?php // phpcs:ignore Generic.Files.LineLength.MaxExceeded ?>
<label for="<?php echo esc_attr( $this->get_field_id( 'showIcon' ) ); ?>">
<?php esc_html_e( 'Show icon', 'aioseo-local-business' ); ?>
</label>
</p>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'width' ) ); ?>">
<?php echo esc_html( __( 'Width', 'aioseo-local-business' ) ); ?>:
</label>
<input
type="text"
id="<?php echo esc_attr( $this->get_field_id( 'width' ) ); ?>"
name="<?php echo esc_attr( $this->get_field_name( 'width' ) ); ?>"
value="<?php echo esc_attr( $instance['width'] ); ?>"
class="widefat"
/>
</p>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'height' ) ); ?>">
<?php echo esc_html( __( 'Height', 'aioseo-local-business' ) ); ?>:
</label>
<input
type="text"
id="<?php echo esc_attr( $this->get_field_id( 'height' ) ); ?>"
name="<?php echo esc_attr( $this->get_field_name( 'height' ) ); ?>"
value="<?php echo esc_attr( $instance['height'] ); ?>"
class="widefat"
/>
</p>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'label' ) ); ?>">
<?php esc_html_e( 'Label', 'aioseo-local-business' ); ?>
</label>
<input
type="text"
id="<?php echo esc_attr( $this->get_field_id( 'label' ) ); ?>"
name="<?php echo esc_attr( $this->get_field_name( 'label' ) ); ?>"
value="<?php echo esc_attr( $instance['label'] ); ?>"
class="widefat"
/>
</p>
<?php
}
} app/Widgets/Locations.php 0000644 00000010717 15172727765 0011427 0 ustar 00 <?php
namespace AIOSEO\Plugin\Addon\LocalBusiness\Widgets;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Class Locations.
*
* @since 1.1.0
*/
class Locations extends \WP_Widget {
/**
* The default attributes.
*
* @since 1.2.12
*
* @var array
*/
private $defaults = [];
/**
* Class constructor.
*
* @since 1.1.0
*/
public function __construct() {
// Widget defaults.
$this->defaults = [
'title' => '',
'categoryId' => ''
];
// Widget Slug.
$widgetSlug = 'aioseo-local-category-widget';
// Widget basics.
$widgetOps = [
'classname' => $widgetSlug,
'description' => esc_html__( 'Display a list of locations by category.', 'aioseo-local-business' ),
];
// Widget controls.
$controlOps = [
'id_base' => $widgetSlug,
];
// Load widget.
parent::__construct( $widgetSlug, esc_html__( 'AIOSEO Local - Locations by Category', 'aioseo-local-business' ), $widgetOps, $controlOps );
}
/**
* Widget callback.
*
* @since 1.1.0
*
* @param array $args Widget args.
* @param array $instance The widget instance options.
* @return void
*/
public function widget( $args, $instance ) {
if ( aioseo()->options->localBusiness->locations->general->multiple ) {
if ( empty( $instance['categoryId'] ) || is_wp_error( get_term( $instance['categoryId'], aioseoLocalBusiness()->taxonomy->getName() ) ) ) {
return;
}
// Merge with defaults.
$instance = wp_parse_args( (array) $instance, $this->defaults );
echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
// Title.
if ( ! empty( $instance['title'] ) ) {
echo $args['before_title'] . apply_filters( 'widget_title', $instance['title'], $instance, $this->id_base ) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped,Generic.Files.LineLength.MaxExceeded
}
// Location info.
if ( ! empty( $instance['categoryId'] ) ) {
aioseoLocalBusiness()->locations->outputLocationCategory( absint( $instance['categoryId'] ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
}
/**
* Widget option update.
*
* @since 1.1.0
*
* @param array $newInstance New instance options.
* @param array $oldInstance Old instance options.
* @return array Processed new instance options.
*/
public function update( $newInstance, $oldInstance ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
$newInstance['title'] = wp_strip_all_tags( $newInstance['title'] );
$newInstance['categoryId'] = ! empty( $newInstance['categoryId'] ) ? (int) $newInstance['categoryId'] : 0;
return $newInstance;
}
/**
* Widget options form.
*
* @since 1.1.0
*
* @param array $instance The widget instance options.
* @return void
*/
public function form( $instance ) {
// Merge with defaults.
$instance = wp_parse_args( (array) $instance, $this->defaults );
?>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>">
<?php echo esc_html( __( 'Title:', 'aioseo-local-business' ) ); ?>
</label>
<input
type="text"
id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"
name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>"
value="<?php echo esc_attr( $instance['title'] ); ?>"
class="widefat"
/>
</p>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'categoryId' ) ); ?>">
<?php echo esc_html__( 'Category:', 'aioseo-local-business' ); ?>
</label>
<select class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'categoryId' ) ); ?>"
name="<?php echo esc_attr( $this->get_field_name( 'categoryId' ) ); ?>">
<?php
$categories = aioseoLocalBusiness()->locations->getLocationCategories();
if ( ! empty( $categories ) ) {
echo '<option value="" selected disabled>' . esc_html__( 'Select a category', 'aioseo-local-business' ) . '</option>';
foreach ( $categories as $category ) {
echo '<option value="' . esc_attr( $category->term_id ) . '" ' . selected( $instance['categoryId'], $category->term_id, false ) . '>';
echo esc_html( $category->name );
echo '</option>';
}
} else {
echo '<option value="">' . esc_html__( 'No categories available', 'aioseo-local-business' ) . '</option>';
}
?>
</select>
</p>
<?php
}
} app/Widgets/OpeningHours.php 0000644 00000025164 15172727765 0012116 0 ustar 00 <?php
namespace AIOSEO\Plugin\Addon\LocalBusiness\Widgets;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Class OpeningHours.
*
* @since 1.1.0
*/
class OpeningHours extends \WP_Widget {
/**
* The default attributes.
*
* @since 1.2.12
*
* @var array
*/
private $defaults = [];
/**
* Class constructor.
*
* @since 1.1.0
*/
public function __construct() {
// Widget defaults.
$this->defaults = [
'title' => '',
'locationId' => '',
'showTitle' => true,
'showIcons' => true,
'showMonday' => true,
'showTuesday' => true,
'showWednesday' => true,
'showThursday' => true,
'showFriday' => true,
'showSaturday' => true,
'showSunday' => true,
'label' => __( 'Our Opening Hours:', 'aioseo-local-business' ),
'after' => '',
];
// Widget Slug.
$widgetSlug = 'aioseo-local-opening-hours-widget';
// Widget basics.
$widgetOps = [
'classname' => $widgetSlug,
'description' => esc_html__( 'Display opening hours of a location.', 'aioseo-local-business' ),
];
// Widget controls.
$controlOps = [
'id_base' => $widgetSlug,
];
// Load widget.
parent::__construct( $widgetSlug, esc_html__( 'AIOSEO Local - Opening Hours', 'aioseo-local-business' ), $widgetOps, $controlOps );
}
/**
* Widget callback.
*
* @since 1.1.0
*
* @param array $args Widget args.
* @param array $instance The widget instance options.
* @return void
*/
public function widget( $args, $instance ) {
// Merge with defaults.
$instance = wp_parse_args( (array) $instance, $this->defaults );
echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
// Title.
if ( ! empty( $instance['title'] ) ) {
echo $args['before_title'] . apply_filters( 'widget_title', $instance['title'], $instance, $this->id_base ) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped,Generic.Files.LineLength.MaxExceeded
}
// Location info.
aioseoLocalBusiness()->locations->outputOpeningHours( $instance['locationId'], $instance ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
// After.
if ( ! empty( $instance['after'] ) ) {
echo $instance['after']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
/**
* Widget option update.
*
* @since 1.1.0
*
* @param array $newInstance New instance options.
* @param array $oldInstance Old instance options.
* @return array Processed new instance options.
*/
public function update( $newInstance, $oldInstance ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
// $newInstance['locationId'] = ! empty( $newInstance['locationId'] ) ? (int) $newInstance['locationId'] : 0;
$newInstance['title'] = wp_kses( $newInstance['title'], 'post' );
$newInstance['showTitle'] = ! empty( $newInstance['showTitle'] ) ? '1' : false;
$newInstance['showIcons'] = ! empty( $newInstance['showIcons'] ) ? '1' : false;
$newInstance['showMonday'] = ! empty( $newInstance['showMonday'] ) ? '1' : false;
$newInstance['showTuesday'] = ! empty( $newInstance['showTuesday'] ) ? '1' : false;
$newInstance['showWednesday'] = ! empty( $newInstance['showWednesday'] ) ? '1' : false;
$newInstance['showThursday'] = ! empty( $newInstance['showThursday'] ) ? '1' : false;
$newInstance['showFriday'] = ! empty( $newInstance['showFriday'] ) ? '1' : false;
$newInstance['showSaturday'] = ! empty( $newInstance['showSaturday'] ) ? '1' : false;
$newInstance['showSunday'] = ! empty( $newInstance['showSunday'] ) ? '1' : false;
$newInstance['after'] = wp_kses( $newInstance['after'], 'post' );
return $newInstance;
}
/**
* Widget options form.
*
* @since 1.1.0
*
* @param array $instance The widget instance options.
* @return void
*/
public function form( $instance ) {
// Merge with defaults.
$instance = wp_parse_args( (array) $instance, $this->defaults );
?>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>">
<?php echo esc_html( __( 'Title:', 'aioseo-local-business' ) ); ?>
</label>
<input
type="text"
id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"
name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>"
value="<?php echo esc_attr( $instance['title'] ); ?>"
class="widefat"
/>
</p>
<?php if ( aioseo()->options->localBusiness->locations->general->multiple ) { ?>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'locationId' ) ); ?>">
<?php echo esc_html__( 'Location:', 'aioseo-local-business' ); ?>
</label>
<select class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'locationId' ) ); ?>"
name="<?php echo esc_attr( $this->get_field_name( 'locationId' ) ); ?>">
<?php
$locations = aioseoLocalBusiness()->locations->getLocations( [
'order_by' => 'post_title',
'order' => 'asc'
] );
if ( ! empty( $locations ) ) {
echo '<option value="" selected disabled>' . esc_html__( 'Select your location', 'aioseo-local-business' ) . '</option>';
foreach ( $locations as $location ) {
echo '<option value="' . esc_attr( $location->ID ) . '" ' . selected( $instance['locationId'], $location->ID, false ) . '>' . esc_html( $location->post_title ) . '</option>'; // phpcs:ignore Generic.Files.LineLength.MaxExceeded
}
} else {
echo '<option value="">' . esc_html__( 'No locations available', 'aioseo-local-business' ) . '</option>';
}
?>
</select>
</p>
<?php } ?>
<p>
<input type="checkbox" id="<?php echo esc_attr( $this->get_field_id( 'showTitle' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'showTitle' ) ); ?>" <?php checked( '1', $instance['showTitle'] ); ?>> <?php // phpcs:ignore Generic.Files.LineLength.MaxExceeded ?>
<label for="<?php echo esc_attr( $this->get_field_id( 'showTitle' ) ); ?>">
<?php esc_html_e( 'Show title', 'aioseo-local-business' ); ?>
</label>
</p>
<p>
<input type="checkbox" id="<?php echo esc_attr( $this->get_field_id( 'showIcons' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'showIcons' ) ); ?>" <?php checked( '1', $instance['showIcons'] ); ?>> <?php // phpcs:ignore Generic.Files.LineLength.MaxExceeded ?>
<label for="<?php echo esc_attr( $this->get_field_id( 'showIcons' ) ); ?>">
<?php esc_html_e( 'Show icons', 'aioseo-local-business' ); ?>
</label>
</p>
<p>
<strong><?php esc_html_e( 'Opening Hours', 'aioseo-local-business' ); ?></strong>
</p>
<p>
<input type="checkbox" id="<?php echo esc_attr( $this->get_field_id( 'showMonday' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'showMonday' ) ); ?>" <?php checked( '1', $instance['showMonday'] ); ?>> <?php // phpcs:ignore Generic.Files.LineLength.MaxExceeded ?>
<label for="<?php echo esc_attr( $this->get_field_id( 'showMonday' ) ); ?>">
<?php esc_html_e( 'Monday', 'aioseo-local-business' ); ?>
</label>
</p>
<p>
<input type="checkbox" id="<?php echo esc_attr( $this->get_field_id( 'showTuesday' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'showTuesday' ) ); ?>" <?php checked( '1', $instance['showTuesday'] ); ?>> <?php // phpcs:ignore Generic.Files.LineLength.MaxExceeded ?>
<label for="<?php echo esc_attr( $this->get_field_id( 'showTuesday' ) ); ?>">
<?php esc_html_e( 'Tuesday', 'aioseo-local-business' ); ?>
</label>
</p>
<p>
<input type="checkbox" id="<?php echo esc_attr( $this->get_field_id( 'showWednesday' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'showWednesday' ) ); ?>" <?php checked( '1', $instance['showWednesday'] ); ?>> <?php // phpcs:ignore Generic.Files.LineLength.MaxExceeded ?>
<label for="<?php echo esc_attr( $this->get_field_id( 'showWednesday' ) ); ?>">
<?php esc_html_e( 'Wednesday', 'aioseo-local-business' ); ?>
</label>
</p>
<p>
<input type="checkbox" id="<?php echo esc_attr( $this->get_field_id( 'showThursday' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'showThursday' ) ); ?>" <?php checked( '1', $instance['showThursday'] ); ?>> <?php // phpcs:ignore Generic.Files.LineLength.MaxExceeded ?>
<label for="<?php echo esc_attr( $this->get_field_id( 'showThursday' ) ); ?>">
<?php esc_html_e( 'Thursday', 'aioseo-local-business' ); ?>
</label>
</p>
<p>
<input type="checkbox" id="<?php echo esc_attr( $this->get_field_id( 'showFriday' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'showFriday' ) ); ?>" <?php checked( '1', $instance['showFriday'] ); ?>> <?php // phpcs:ignore Generic.Files.LineLength.MaxExceeded ?>
<label for="<?php echo esc_attr( $this->get_field_id( 'showFriday' ) ); ?>">
<?php esc_html_e( 'Friday', 'aioseo-local-business' ); ?>
</label>
</p>
<p>
<input type="checkbox" id="<?php echo esc_attr( $this->get_field_id( 'showSaturday' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'showSaturday' ) ); ?>" <?php checked( '1', $instance['showSaturday'] ); ?>> <?php // phpcs:ignore Generic.Files.LineLength.MaxExceeded ?>
<label for="<?php echo esc_attr( $this->get_field_id( 'showSaturday' ) ); ?>">
<?php esc_html_e( 'Saturday', 'aioseo-local-business' ); ?>
</label>
</p>
<p>
<input type="checkbox" id="<?php echo esc_attr( $this->get_field_id( 'showSunday' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'showSunday' ) ); ?>" <?php checked( '1', $instance['showSunday'] ); ?>> <?php // phpcs:ignore Generic.Files.LineLength.MaxExceeded ?>
<label for="<?php echo esc_attr( $this->get_field_id( 'showSunday' ) ); ?>">
<?php esc_html_e( 'Sunday', 'aioseo-local-business' ); ?>
</label>
</p>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'label' ) ); ?>">
<?php esc_html_e( 'Label', 'aioseo-local-business' ); ?>
</label>
<input
type="text"
id="<?php echo esc_attr( $this->get_field_id( 'label' ) ); ?>"
name="<?php echo esc_attr( $this->get_field_name( 'label' ) ); ?>"
value="<?php echo esc_attr( $instance['label'] ); ?>"
class="widefat"
/>
</p>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'after' ) ); ?>">
<?php echo esc_html__( 'After widget text:', 'aioseo-local-business' ); ?>
</label><br />
<textarea id="<?php echo esc_attr( $this->get_field_id( 'after' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'after' ) ); ?>" class="widefat"><?php echo esc_attr( $instance['after'] ); ?></textarea> <?php // phpcs:ignore Generic.Files.LineLength.MaxExceeded ?>
</p>
<?php
}
} app/Widgets/BusinessInfo.php 0000644 00000027772 15172727765 0012114 0 ustar 00 <?php
namespace AIOSEO\Plugin\Addon\LocalBusiness\Widgets;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* AIOSEO Business Info widget.
*
* @since 1.1.0
*/
class BusinessInfo extends \WP_Widget {
/**
* The default attributes.
*
* @since 1.2.12
*
* @var array
*/
private $defaults = [];
/**
* Class constructor.
*
* @since 1.1.0
*/
public function __construct() {
// Widget defaults.
$this->defaults = [
'title' => '',
'locationId' => '',
'showLabels' => true,
'showIcons' => true,
'showName' => true,
'showAddress' => true,
'showPhone' => true,
'showFax' => true,
'showCountryCode' => true,
'showEmail' => true,
'showVat' => true,
'showTax' => true,
'addressLabel' => __( 'Address:', 'aioseo-local-business' ),
'vatIdLabel' => __( 'VAT ID:', 'aioseo-local-business' ),
'taxIdLabel' => __( 'Tax ID:', 'aioseo-local-business' ),
'phoneLabel' => __( 'Phone:', 'aioseo-local-business' ),
'faxLabel' => __( 'Fax:', 'aioseo-local-business' ),
'emailLabel' => __( 'Email:', 'aioseo-local-business' ),
'after' => '',
];
// Widget Slug.
$widgetSlug = 'aioseo-local-business-info-widget';
// Widget basics.
$widgetOps = [
'classname' => $widgetSlug,
'description' => esc_html__( 'Display a location information.', 'aioseo-local-business' ),
];
// Widget controls.
$controlOps = [
'id_base' => $widgetSlug,
];
// Load widget.
parent::__construct( $widgetSlug, esc_html__( 'AIOSEO Local - Business Info', 'aioseo-local-business' ), $widgetOps, $controlOps );
}
/**
* Widget callback.
*
* @since 1.1.0
*
* @param array $args Widget args.
* @param array $instance The widget instance options.
* @return void
*/
public function widget( $args, $instance ) {
// Merge with defaults.
$instance = wp_parse_args( (array) $instance, $this->defaults );
echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
// Title.
if ( ! empty( $instance['title'] ) ) {
echo $args['before_title'] . apply_filters( 'widget_title', $instance['title'], $instance, $this->id_base ) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped,Generic.Files.LineLength.MaxExceeded
}
// Location info.
aioseoLocalBusiness()->locations->outputBusinessInfo( $instance['locationId'], $instance );
// After.
if ( ! empty( $instance['after'] ) ) {
echo $instance['after']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
/**
* Widget option update.
*
* @since 1.1.0
*
* @param array $newInstance New instance options.
* @param array $oldInstance Old instance options.
* @return array Processed new instance options.
*/
public function update( $newInstance, $oldInstance ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
// $newInstance['locationId'] = ! empty( $newInstance['locationId'] ) ? (int) $newInstance['locationId'] : 0;
$newInstance['title'] = wp_strip_all_tags( $newInstance['title'] );
$newInstance['showLabels'] = ! empty( $newInstance['showLabels'] ) ? '1' : false;
$newInstance['showIcons'] = ! empty( $newInstance['showIcons'] ) ? '1' : false;
$newInstance['showName'] = ! empty( $newInstance['showName'] ) ? '1' : false;
$newInstance['showAddress'] = ! empty( $newInstance['showAddress'] ) ? '1' : false;
$newInstance['showPhone'] = ! empty( $newInstance['showPhone'] ) ? '1' : false;
$newInstance['showFax'] = ! empty( $newInstance['showFax'] ) ? '1' : false;
$newInstance['showCountryCode'] = ! empty( $newInstance['showCountryCode'] ) ? '1' : false;
$newInstance['showEmail'] = ! empty( $newInstance['showEmail'] ) ? '1' : false;
$newInstance['showVat'] = ! empty( $newInstance['showVat'] ) ? '1' : false;
$newInstance['showTax'] = ! empty( $newInstance['showTax'] ) ? '1' : false;
$newInstance['after'] = wp_strip_all_tags( $newInstance['after'] );
return $newInstance;
}
/**
* Widget options form.
*
* @since 1.1.0
*
* @param array $instance The widget instance options.
* @return void
*/
public function form( $instance ) {
// Merge with defaults.
$instance = wp_parse_args( (array) $instance, $this->defaults );
?>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>">
<?php echo esc_html( __( 'Title:', 'aioseo-local-business' ) ); ?>
</label>
<input
type="text"
id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"
name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>"
value="<?php echo esc_attr( $instance['title'] ); ?>"
class="widefat"
/>
</p>
<?php if ( aioseo()->options->localBusiness->locations->general->multiple ) { ?>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'locationId' ) ); ?>">
<?php esc_html_e( 'Location:', 'aioseo-local-business' ); ?>
</label>
<select class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'locationId' ) ); ?>"
name="<?php echo esc_attr( $this->get_field_name( 'locationId' ) ); ?>">
<?php
$locations = aioseoLocalBusiness()->locations->getLocations( [
'order_by' => 'post_title',
'order' => 'asc'
] );
if ( ! empty( $locations ) ) {
echo '<option value="" selected disabled>' . esc_html__( 'Select your location', 'aioseo-local-business' ) . '</option>';
foreach ( $locations as $location ) {
echo '<option value="' . esc_attr( $location->ID ) . '" ' . selected( $instance['locationId'], $location->ID, false ) . '>' . esc_html( $location->post_title ) . '</option>'; // phpcs:ignore Generic.Files.LineLength.MaxExceeded
}
} else {
echo '<option value="">' . esc_html__( 'No locations available', 'aioseo-local-business' ) . '</option>';
}
?>
</select>
</p>
<?php } ?>
<p>
<input type="checkbox" id="<?php echo esc_attr( $this->get_field_id( 'showLabels' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'showLabels' ) ); ?>" <?php checked( '1', $instance['showLabels'] ); ?>> <?php // phpcs:ignore Generic.Files.LineLength.MaxExceeded ?>
<label for="<?php echo esc_attr( $this->get_field_id( 'showLabels' ) ); ?>">
<?php esc_html_e( 'Show labels', 'aioseo-local-business' ); ?>
</label>
</p>
<p>
<input type="checkbox" id="<?php echo esc_attr( $this->get_field_id( 'showIcons' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'showIcons' ) ); ?>" <?php checked( '1', $instance['showIcons'] ); ?>> <?php // phpcs:ignore Generic.Files.LineLength.MaxExceeded ?>
<label for="<?php echo esc_attr( $this->get_field_id( 'showIcons' ) ); ?>">
<?php esc_html_e( 'Show icons', 'aioseo-local-business' ); ?>
</label>
</p>
<p>
<strong><?php esc_html_e( 'Business Info:', 'aioseo-local-business' ); ?></strong>
</p>
<p>
<input type="checkbox" id="<?php echo esc_attr( $this->get_field_id( 'showName' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'showName' ) ); ?>" <?php checked( '1', $instance['showName'] ); ?>> <?php // phpcs:ignore Generic.Files.LineLength.MaxExceeded ?>
<label for="<?php echo esc_attr( $this->get_field_id( 'showName' ) ); ?>">
<?php esc_html_e( 'Business name', 'aioseo-local-business' ); ?>
</label>
</p>
<p>
<input type="checkbox" id="<?php echo esc_attr( $this->get_field_id( 'showAddress' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'showAddress' ) ); ?>" <?php checked( '1', $instance['showAddress'] ); ?>> <?php // phpcs:ignore Generic.Files.LineLength.MaxExceeded ?>
<label for="<?php echo esc_attr( $this->get_field_id( 'showAddress' ) ); ?>">
<?php esc_html_e( 'Address', 'aioseo-local-business' ); ?>
</label>
</p>
<p>
<input type="checkbox" id="<?php echo esc_attr( $this->get_field_id( 'showPhone' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'showPhone' ) ); ?>" <?php checked( '1', $instance['showPhone'] ); ?>> <?php // phpcs:ignore Generic.Files.LineLength.MaxExceeded ?>
<label for="<?php echo esc_attr( $this->get_field_id( 'showPhone' ) ); ?>">
<?php esc_html_e( 'Phone Number', 'aioseo-local-business' ); ?>
</label>
</p>
<p>
<input type="checkbox" id="<?php echo esc_attr( $this->get_field_id( 'showFax' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'showFax' ) ); ?>" <?php checked( '1', $instance['showFax'] ); ?>> <?php // phpcs:ignore Generic.Files.LineLength.MaxExceeded ?>
<label for="<?php echo esc_attr( $this->get_field_id( 'showFax' ) ); ?>">
<?php esc_html_e( 'Fax Number', 'aioseo-local-business' ); ?>
</label>
</p>
<p>
<input type="checkbox" id="<?php echo esc_attr( $this->get_field_id( 'showCountryCode' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'showCountryCode' ) ); ?>" <?php checked( '1', $instance['showCountryCode'] ); ?>> <?php // phpcs:ignore Generic.Files.LineLength.MaxExceeded ?>
<label for="<?php echo esc_attr( $this->get_field_id( 'showCountryCode' ) ); ?>">
<?php esc_html_e( 'Show Country Code', 'aioseo-local-business' ); ?>
</label>
</p>
<p>
<input type="checkbox" id="<?php echo esc_attr( $this->get_field_id( 'showEmail' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'showEmail' ) ); ?>" <?php checked( '1', $instance['showEmail'] ); ?>> <?php // phpcs:ignore Generic.Files.LineLength.MaxExceeded ?>
<label for="<?php echo esc_attr( $this->get_field_id( 'showEmail' ) ); ?>">
<?php esc_html_e( 'Email address', 'aioseo-local-business' ); ?>
</label>
</p>
<p>
<input type="checkbox" id="<?php echo esc_attr( $this->get_field_id( 'showVat' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'showVat' ) ); ?>" <?php checked( '1', $instance['showVat'] ); ?>> <?php // phpcs:ignore Generic.Files.LineLength.MaxExceeded ?>
<label for="<?php echo esc_attr( $this->get_field_id( 'showVat' ) ); ?>">
<?php esc_html_e( 'Show VAT ID', 'aioseo-local-business' ); ?>
</label>
</p>
<p>
<input type="checkbox" id="<?php echo esc_attr( $this->get_field_id( 'showTax' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'showTax' ) ); ?>" <?php checked( '1', $instance['showTax'] ); ?>> <?php // phpcs:ignore Generic.Files.LineLength.MaxExceeded ?>
<label for="<?php echo esc_attr( $this->get_field_id( 'showTax' ) ); ?>">
<?php esc_html_e( 'Show Tax ID', 'aioseo-local-business' ); ?>
</label>
</p>
<p><strong><?php echo esc_html( __( 'Labels:', 'aioseo-local-business' ) ); ?></strong></p>
<p class="labels">
<?php
$labels = [
'addressLabel' => __( 'Address', 'aioseo-local-business' ),
'vatIdLabel' => __( 'Vat ID', 'aioseo-local-business' ),
'taxIdLabel' => __( 'Tax ID', 'aioseo-local-business' ),
'phoneLabel' => __( 'Phone', 'aioseo-local-business' ),
'faxLabel' => __( 'Fax', 'aioseo-local-business' ),
'emailLabel' => __( 'Email', 'aioseo-local-business' )
]
?>
<?php foreach ( $labels as $labelKey => $label ) { ?>
<label for="<?php echo esc_attr( $this->get_field_id( $labelKey ) ); ?>">
<?php echo esc_html( $label ); ?>
</label>
<input
type="text"
id="<?php echo esc_attr( $this->get_field_id( $labelKey ) ); ?>"
name="<?php echo esc_attr( $this->get_field_name( $labelKey ) ); ?>"
value="<?php echo esc_attr( $instance[ $labelKey ] ); ?>"
class="widefat"
/>
<?php } ?>
</p>
<p>
<label for="<?php echo esc_attr( $this->get_field_id( 'after' ) ); ?>">
<?php esc_html_e( 'After widget text:', 'aioseo-local-business' ); ?>
</label><br />
<textarea id="<?php echo esc_attr( $this->get_field_id( 'after' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'after' ) ); ?>" class="widefat"><?php echo esc_attr( $instance['after'] ); ?></textarea> <?php // phpcs:ignore Generic.Files.LineLength.MaxExceeded ?>
</p>
<?php
}
} app/Widgets/Widgets.php 0000644 00000001415 15172727766 0011076 0 ustar 00 <?php
namespace AIOSEO\Plugin\Addon\LocalBusiness\Widgets;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Class Widgets.
*
* @since 1.1.0
*/
class Widgets {
/**
* Widgets constructor.
*
* @since 1.1.0
*/
public function __construct() {
add_action( 'widgets_init', [ $this, 'registerWidgets' ] );
}
/**
* Register AIOSEO plugin widgets.
*
* @since 1.1.0
*
* @return void
*/
public function registerWidgets() {
register_widget( 'AIOSEO\Plugin\Addon\LocalBusiness\Widgets\BusinessInfo' );
register_widget( 'AIOSEO\Plugin\Addon\LocalBusiness\Widgets\Locations' );
register_widget( 'AIOSEO\Plugin\Addon\LocalBusiness\Widgets\OpeningHours' );
register_widget( 'AIOSEO\Plugin\Addon\LocalBusiness\Widgets\Map' );
}
} app/Schema/Graphs/KgOrganization.php 0000644 00000002355 15172727766 0013440 0 ustar 00 <?php
namespace AIOSEO\Plugin\Addon\LocalBusiness\Schema\Graphs;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Knowledge Graph Organization graph class.
*
* @since 1.3.3
*/
class KgOrganization extends Base {
/**
*The data for the global options.
*
* @since 1.3.3
*
* @var object|null
*/
protected $dataObject = null;
/**
* Class constructor.
*
* @since 1.3.3
*/
public function __construct() {
$this->dataObject = aioseoLocalBusiness()->helpers->getLocalBusinessOptions();
}
/**
* Returns the graph data.
*
* @since 1.3.3
*
* @return void
*/
public function get() {}
/**
* Returns the graph data.
*
* @since 1.3.3
*
* @return array $data The graph data.
*/
public function getAdditionalGraphData( $postId, $data ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
if ( aioseo()->options->localBusiness->locations->general->multiple ) {
return $data;
}
$additionalData = [
'address' => $this->address()
];
if ( empty( $data['email'] ) ) {
$additionalData['email'] = $this->dataObject->locations->business->contact->email;
}
$additionalData += $this->ids();
return array_merge( $data, $additionalData );
}
} app/Schema/Graphs/LocalBusiness.php 0000644 00000015045 15172727766 0013260 0 ustar 00 <?php
namespace AIOSEO\Plugin\Addon\LocalBusiness\Schema\Graphs;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* LocalBusiness graph class.
*
* @since 1.0.0
*/
class LocalBusiness extends Base {
/**
* The Local SEO post ID.
*
* @since 1.1.0
*
* @var integer
*/
private $postId = null;
/**
*The data for the CPT or the global options.
*
* @since 1.1.0
*
* @var object|null
*/
protected $dataObject = null;
/**
* Class constructor.
*
* @since 1.1.0
*/
public function __construct() {
$this->dataObject = aioseoLocalBusiness()->helpers->getLocalBusinessOptions();
$postId = get_the_ID();
if ( $postId && get_post_type( $postId ) === aioseoLocalBusiness()->postType->getName() ) {
$this->postId = $postId;
$this->dataObject = aioseoLocalBusiness()->locations->getLocation( $postId );
}
}
/**
* Returns the graph data.
*
* @since 1.0.0
*
* @return array The graph data.
*/
public function get() {
if ( empty( $this->dataObject ) ) {
return [];
}
$data = [
'@type' => $this->businessType(),
'@id' => trailingslashit( home_url() ) . '#localbusiness',
'name' => $this->name(),
'brand' => [
'@id' => trailingslashit( home_url() ) . '#organization'
],
'url' => $this->postId ? get_permalink( $this->postId ) : trailingslashit( home_url() ),
'image' => $this->businessImage(),
'logo' => $this->postId ? get_permalink( $this->postId ) . '#logo' : trailingslashit( home_url() ) . '#logo',
'address' => $this->address(),
'email' => $this->dataObject->locations->business->contact->email,
'telephone' => $this->phoneNumber(),
'faxNumber' => $this->dataObject->locations->business->contact->fax,
'priceRange' => $this->dataObject->locations->business->payment->priceRange,
'currenciesAccepted' => $this->acceptedCurrencies(),
'paymentAccepted' => $this->dataObject->locations->business->payment->methods,
'areaServed' => $this->dataObject->locations->business->areaServed,
'openingHoursSpecification' => $this->openingHours()
];
if ( $data['address'] ) {
$data['location'] = [
'@id' => trailingslashit( home_url() ) . '#postaladdress'
];
}
$data += $this->ids();
return $data;
}
/**
* Returns the business type.
*
* @since 1.0.0
*
* @return string $businessType The business type.
*/
private function businessType() {
$businessType = $this->dataObject->locations->business->businessType;
if ( is_object( $businessType ) ) {
$businessType = $businessType->value;
}
return ! empty( $businessType ) ? $businessType : 'LocalBusiness';
}
/**
* Returns the name.
*
* @since 1.0.0
*
* @return string $name The name.
*/
private function name() {
$name = $this->dataObject->locations->business->name;
if ( $name ) {
return $name;
}
// Default a single location to its post title.
if ( $this->postId ) {
$name = get_the_title( $this->postId );
if ( $name ) {
return $name;
}
}
$name = aioseo()->tags->replaceTags( aioseo()->options->searchAppearance->global->schema->organizationName );
if ( $name ) {
return $name;
}
return aioseo()->helpers->decodeHtmlEntities( get_bloginfo( 'name' ) );
}
/**
* Returns the image.
*
* @since 1.0.0
*
* @return string $image The image.
*/
private function businessImage() {
$image = $this->dataObject->locations->business->image;
if ( $image ) {
return $image;
}
// Default a single location to it's post title.
if ( $this->postId ) {
$image = get_the_post_thumbnail_url( $this->postId, 'full' );
if ( $image ) {
return $image;
}
}
// Fallback to Organization Logo.
$image = aioseo()->options->searchAppearance->global->schema->organizationLogo;
if ( $image ) {
return $image;
}
// Fallback to Site Logo.
return aioseo()->helpers->getSiteLogoUrl();
}
/**
* Returns the phone number.
*
* @since 1.0.0
*
* @return string The phone number.
*/
private function phoneNumber() {
$phoneNumber = $this->dataObject->locations->business->contact->phone;
if ( $phoneNumber ) {
return $phoneNumber;
}
// Fallback to Organization Phone.
$phoneNumber = aioseo()->options->searchAppearance->global->schema->phone;
if ( $phoneNumber ) {
return $phoneNumber;
}
return false;
}
/**
* Returns the accepted currencies.
*
* @since 1.0.0
*
* @return string The accepted currencies as a string, separated by commas.
*/
private function acceptedCurrencies() {
$currencies = $this->dataObject->locations->business->payment->currenciesAccepted;
$rawCurrencies = ! empty( $currencies ) ? json_decode( $currencies ) : $currencies;
if ( ! $rawCurrencies ) {
return '';
}
$currencies = [];
foreach ( $rawCurrencies as $currency ) {
$currencies[] = $currency->value;
}
return ! empty( $currencies ) ? implode( ', ', $currencies ) : '';
}
/**
* Returns the opening hours.
*
* @since 1.0.0
*
* @return array The opening hours.
*/
private function openingHours() {
$openingHoursObject = $this->dataObject->openingHours;
if ( isset( $openingHoursObject->useDefaults ) && true === $openingHoursObject->useDefaults ) {
$openingHoursObject = aioseoLocalBusiness()->helpers->getLocalBusinessOptions()->openingHours;
}
if ( ! $openingHoursObject->show ) {
return [];
}
if ( $openingHoursObject->alwaysOpen ) {
return [
'@type' => 'OpeningHoursSpecification',
'dayOfWeek' => [
'https://schema.org/Monday',
'https://schema.org/Tuesday',
'https://schema.org/Wednesday',
'https://schema.org/Thursday',
'https://schema.org/Friday',
'https://schema.org/Saturday',
'https://schema.org/Sunday'
],
'opens' => '00:00',
'closes' => '23:59'
];
}
$days = [];
foreach ( $openingHoursObject->days as $day => $values ) {
if ( $values->closed ) {
continue;
}
if ( $values->open24h ) {
$days[] = [
'@type' => 'OpeningHoursSpecification',
'dayOfWeek' => [
'https://schema.org/' . ucfirst( $day )
],
'opens' => '00:00',
'closes' => '23:59'
];
continue;
}
$days[] = [
'@type' => 'OpeningHoursSpecification',
'dayOfWeek' => [
'https://schema.org/' . ucfirst( $day )
],
'opens' => $values->openTime,
'closes' => $values->closeTime
];
}
return $days;
}
} app/Schema/Graphs/Base.php 0000644 00000004757 15172727766 0011374 0 ustar 00 <?php
namespace AIOSEO\Plugin\Addon\LocalBusiness\Schema\Graphs;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
use AIOSEO\Plugin\Common\Schema\Graphs as CommonGraphs;
/**
* Base graph class.
*
* @since 1.3.3
*/
abstract class Base extends CommonGraphs\Graph {
/**
*The data for the CPT or the global options.
*
* @since 1.3.3
*
* @var object|null
*/
protected $dataObject = null;
/**
* Returns the address.
*
* @since 1.0.0
* @version 1.3.3 Moved to abstract class.
*
* @return array The address.
*/
protected function address() {
if (
! $this->dataObject->locations->business->address->streetLine1 &&
! $this->dataObject->locations->business->address->streetLine2
) {
return [];
}
return [
'@id' => trailingslashit( home_url() ) . '#postaladdress',
'@type' => 'PostalAddress',
'streetAddress' => sprintf(
'%1$s, %2$s',
$this->dataObject->locations->business->address->streetLine1,
$this->dataObject->locations->business->address->streetLine2
),
'postalCode' => $this->dataObject->locations->business->address->zipCode,
'addressLocality' => $this->dataObject->locations->business->address->city,
'addressRegion' => $this->dataObject->locations->business->address->state,
'addressCountry' => $this->dataObject->locations->business->address->country
];
}
/**
* Returns the IDs.
*
* @since 1.3.3
*
* @return array The ids.
*/
protected function ids() {
$ids = [
'taxID' => $this->dataObject->locations->business->ids->tax ?? '',
'vatID' => $this->dataObject->locations->business->ids->vat ?? '',
'iso6523Code' => $this->dataObject->locations->business->ids->iso6523 ?? '',
'leiCode' => $this->dataObject->locations->business->ids->lei ?? '',
'duns' => $this->dataObject->locations->business->ids->duns ?? '',
'naics' => $this->dataObject->locations->business->ids->naics ?? '',
'globalLocationNumber' => $this->dataObject->locations->business->ids->gs1 ?? ''
];
if ( empty( $ids['iso6523Code'] ) && ! empty( $ids['duns'] ) ) {
$ids['iso6523Code'] = '0060:' . $ids['duns'];
}
if ( empty( $ids['iso6523Code'] ) && ! empty( $ids['globalLocationNumber'] ) ) {
$ids['iso6523Code'] = '0088:' . $ids['globalLocationNumber'];
}
if ( empty( $ids['iso6523Code'] ) && ! empty( $ids['leiCode'] ) ) {
$ids['iso6523Code'] = '0199:' . $ids['leiCode'];
}
return array_filter( $ids );
}
} app/Schema/Schema.php 0000644 00000002051 15172727766 0010457 0 ustar 00 <?php
namespace AIOSEO\Plugin\Addon\LocalBusiness\Schema;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Builds our schema.
*
* @since 1.0.0
*/
class Schema {
/**
* Determines which graphs need to be output.
*
* @since 1.1.0
* @version 1.3.0
*
* @return array A list of graphs that need to be output.
*/
public function determineGraphsAndContext() {
if ( ! aioseo()->options->localBusiness->locations->general->multiple ) {
return is_front_page() || ( aioseo()->helpers->isStaticHomepage() && aioseo()->schema->generatingValidatorOutput ) ? [ 'LocalBusiness' ] : [];
}
return is_singular( aioseoLocalBusiness()->postType->getName() ) ? [ 'LocalBusiness' ] : [];
}
/**
* Returns data for the given graph if it's contained within this addon.
*
* @since 1.0.0
*
* @return array The graph data.
*/
public function get( $graphName ) {
$namespace = __NAMESPACE__ . "\Graphs\\$graphName";
if ( ! class_exists( $namespace ) ) {
return [];
}
return ( new $namespace() )->get();
}
} app/Utils/Cache.php 0000644 00000000600 15172727766 0010160 0 ustar 00 <?php
namespace AIOSEO\Plugin\Addon\LocalBusiness\Utils;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Main class for redirects cache.
*
* @since 1.3.0
*/
class Cache extends \AIOSEO\Plugin\Common\Utils\Cache {
/**
* The redirect addon cache prefix.
*
* @since 1.3.0
*
* @var string
*/
protected $prefix = 'aioseo_local_business_';
} app/Utils/InternalOptions.php 0000644 00000003352 15172727767 0012315 0 ustar 00 <?php
namespace AIOSEO\Plugin\Addon\LocalBusiness\Utils;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
use AIOSEO\Plugin\Common\Traits;
/**
* Class that holds all internal options for AIOSEO.
*
* @since 1.1.0.2
*/
class InternalOptions {
use Traits\Options;
/**
* All the default options.
*
* @since 1.1.0.2
*
* @var array
*/
protected $defaults = [
// phpcs:disable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound
'internal' => [
'lastActiveVersion' => [ 'type' => 'string', 'default' => '0.0' ]
]
// phpcs:enable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound
];
/**
* Holds a list of all the possible deprecated options.
*
* @since 1.2.12
*
* @var array
*/
protected $allDeprecatedOptions = [];
/**
* The Construct method.
*
* @since 1.1.0.2
*
* @param string $optionsName An array of options.
*/
public function __construct( $optionsName = 'aioseo_local_seo_options_internal' ) {
$this->optionsName = $optionsName;
$this->init();
add_action( 'shutdown', [ $this, 'save' ] );
}
/**
* Initializes the options.
*
* @since 1.1.0.2
*
* @return void
*/
protected function init() {
// Options from the DB.
$dbOptions = json_decode( get_option( $this->optionsName ), true );
if ( empty( $dbOptions ) ) {
$dbOptions = [];
}
// Refactor options.
$this->defaultsMerged = array_replace_recursive( $this->defaults, $this->defaultsMerged );
$options = array_replace_recursive(
$this->defaultsMerged,
$this->addValueToValuesArray( $this->defaultsMerged, $dbOptions )
);
aioseo()->core->optionsCache->setOptions( $this->optionsName, apply_filters( 'aioseo_get_local_seo_options_internal', $options ) );
}
} app/Utils/Templates.php 0000644 00000001300 15172727767 0011112 0 ustar 00 <?php
namespace AIOSEO\Plugin\Addon\LocalBusiness\Utils;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
use AIOSEO\Plugin\Common\Utils\Templates as CommonTemplates;
/**
* Class Templates
*
* @since 1.1.0
*/
class Templates extends CommonTemplates {
/**
* This plugin absolute path.
*
* @since 1.1.0
*
* @var string
*/
protected $pluginPath = AIOSEO_LOCAL_BUSINESS_PATH;
/**
* Paths were our template files are located.
*
* @since 1.1.0
*
* @var string Array of paths.
*/
protected $paths = [
'app/Views'
];
/**
* Subpath for theme usage.
*
* @since 1.1.0
*
* @var string
*/
protected $themeTemplateSubpath = 'localBusiness';
} app/Utils/Access.php 0000644 00000003017 15172727767 0010364 0 ustar 00 <?php
namespace AIOSEO\Plugin\Addon\LocalBusiness\Utils;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* The Access class.
*
* @since 1.1.0
*/
class Access {
/**
* The Access class instance from the main plugin.
*
* @since 1.1.0
*
* @var \AIOSEO\Plugin\Pro\Utils\Access
*/
public $access;
/**
* Class constructor.
*
* @since 1.1.0
*/
public function __construct() {
$this->access = aioseo()->access;
}
/**
* Add needed capabilities to run Local Business.
*
* @since 1.1.0
*
* @return void
*/
public function addCapabilities() {
foreach ( $this->access->getRoles() as $wpRole => $role ) {
$roleObject = get_role( $wpRole );
if ( ! is_object( $roleObject ) ) {
continue;
}
if ( ! $this->access->hasCapability( 'aioseo_page_local_seo_settings', $role ) ) {
foreach ( aioseoLocalBusiness()->postType->getCapabilities() as $postCapability ) {
$roleObject->remove_cap( $postCapability );
}
foreach ( aioseoLocalBusiness()->taxonomy->getCapabilities() as $taxCapability ) {
$roleObject->remove_cap( $taxCapability );
}
}
if ( $this->access->isAdmin( $role ) || $this->access->hasCapability( 'aioseo_page_local_seo_settings', $role ) ) {
foreach ( aioseoLocalBusiness()->postType->getCapabilities() as $postCapability ) {
$roleObject->add_cap( $postCapability );
}
foreach ( aioseoLocalBusiness()->taxonomy->getCapabilities() as $taxCapability ) {
$roleObject->add_cap( $taxCapability );
}
}
}
}
} app/Utils/Helpers.php 0000644 00000013577 15172727767 0010601 0 ustar 00 <?php
namespace AIOSEO\Plugin\Addon\LocalBusiness\Utils;
use AIOSEO\Plugin\Addon\LocalBusiness\Models\Post;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* The Helpers class.
*
* @since 1.1.0
*/
class Helpers {
/**
* Returns the global Local SEO options as an object.
*
* @since 1.1.0
*
* @return object Global Local SEO options as an object.
*/
public function getLocalBusinessOptions() {
return json_decode( wp_json_encode( aioseo()->options->localBusiness->all(), JSON_FORCE_OBJECT ) );
}
/**
* Returns current permalink structure for this post type.
*
* @since 1.1.0
*
* @param string $postTypeName The post type name.
* @param string $postTypeSlug The post type slug.
* @return string The loaded permastruct or a default if not enabled yet.
*/
public function getPermaStructure( $postTypeName, $postTypeSlug ) {
global $wp_rewrite;
$structure = $wp_rewrite->get_extra_permastruct( $postTypeName );
if ( ! $structure ) {
$structure = '/' . $postTypeSlug . '/%' . $postTypeName . '%/';
}
// Account for trailing slashes.
return user_trailingslashit( $structure );
}
/**
* Gets the data for vue.
*
* @since 1.1.0
*
* @param array $data The parent data array to modify.
* @param string $page The current page.
* @return array An array of data.
*/
public function getVueData( $data = [], $page = null ) {
$data['localBusiness'] = [
'postTypeName' => aioseoLocalBusiness()->postType->getName(),
'postTypeEditLink' => aioseoLocalBusiness()->postType->getEditLink(),
'postTypeDefaultSlug' => aioseoLocalBusiness()->postType->getDefaultSlug(),
'postTypeSingleLabel' => aioseoLocalBusiness()->postType->getSingleLabel(),
'postTypePluralLabel' => aioseoLocalBusiness()->postType->getPluralLabel(),
'taxonomyName' => aioseoLocalBusiness()->taxonomy->getName(),
'taxonomyDefaultSlug' => aioseoLocalBusiness()->taxonomy->getDefaultSlug(),
'taxonomySingleLabel' => aioseoLocalBusiness()->taxonomy->getSingleLabel(),
'taxonomyPluralLabel' => aioseoLocalBusiness()->taxonomy->getPluralLabel(),
'mapLoadEvent' => aioseoLocalBusiness()->maps->mapLoadEvent,
'mapDefaults' => [
'center' => [
'lat' => aioseo()->options->localBusiness->maps->mapOptions->center->getDefault( 'lat' ),
'lng' => aioseo()->options->localBusiness->maps->mapOptions->center->getDefault( 'lng' )
],
'zoom' => aioseo()->options->localBusiness->maps->mapOptions->getDefault( 'zoom' )
],
'importers' => aioseoLocalBusiness()->import->plugins()
];
if ( ! empty( $data['currentPost'] ) && 'post' === $data['currentPost']['context'] && aioseoLocalBusiness()->postType->getName() === $data['currentPost']['postType'] ) {
$locationData = aioseoLocalBusiness()->locations->getLocation( $data['currentPost']['id'] );
$data['currentPost']['local_seo'] = Post::parseLocalSeoOptions( $locationData );
$data['currentPost']['local_seo']['maps']['geocodeAddress'] = $this->addressToGeocode( $data['currentPost']['local_seo']['locations']['business']['address'] );
$locationCategories = wp_get_object_terms(
$data['currentPost']['id'],
aioseoLocalBusiness()->taxonomy->getName(),
[ 'fields' => 'ids' ]
);
$data['currentPost']['localBusinessCategory'] = current( $locationCategories ) ?: [];
// Disable TruSEO.
$data['options']['advanced']['truSeo'] = false;
}
if ( aioseo()->helpers->isScreenBase( 'edit' ) && aioseo()->helpers->isScreenPostType( aioseoLocalBusiness()->postType->getName() ) ) {
// Disable TruSEO.
$data['options']['advanced']['truSeo'] = false;
}
if ( 'local-seo' === $page ) {
$cptStructure = aioseoLocalBusiness()->postType->getPermaStructure();
if ( ! empty( $cptStructure ) and stripos( $cptStructure, aioseoLocalBusiness()->postType->getSlug() ) !== false ) {
$cptStructure = preg_split( '~\/(' . aioseoLocalBusiness()->postType->getSlug() . ')\/~', $cptStructure, - 1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY );
foreach ( $cptStructure as &$cptStructureItem ) {
if ( aioseoLocalBusiness()->postType->getSlug() === $cptStructureItem ) {
$cptStructureItem = '{slug}';
} else {
$cptStructureItem = '/' . $cptStructureItem;
}
}
}
$taxStructure = aioseoLocalBusiness()->taxonomy->getPermaStructure();
if ( ! empty( $taxStructure ) and stripos( $taxStructure, aioseoLocalBusiness()->taxonomy->getSlug() ) !== false ) {
$taxStructure = preg_split( '~\/(' . aioseoLocalBusiness()->taxonomy->getSlug() . ')\/~', $taxStructure, - 1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY );
foreach ( $taxStructure as &$taxStructureItem ) {
if ( aioseoLocalBusiness()->taxonomy->getSlug() === $taxStructureItem ) {
$taxStructureItem = '{slug}';
} else {
$taxStructureItem = '/' . $taxStructureItem;
}
}
}
$data['localBusiness']['postTypePermalinkStructure'] = $cptStructure;
$data['localBusiness']['taxonomyPermalinkStructure'] = $taxStructure;
// getDataObject() pulls from the options state, which is why we use that as the first level here.
$data['options']['localBusiness']['maps']['geocodeAddress'] = $this->addressToGeocode( aioseo()->options->localBusiness->locations->business->address->all() );
$data['localBusiness']['enhancedSearchTest'] = aioseoLocalBusiness()->search->testSearch();
}
return $data;
}
/**
* Returns a format address for Google's geocoding.
*
* @since 1.2.1
*
* @param array $address The address array.
* @return string The formatted address.
*/
private function addressToGeocode( $address ) {
$address = [
$address['streetLine1'],
$address['streetLine2'],
$address['city'],
$address['state'],
$address['country'],
$address['zipCode']
];
return implode( ',', array_filter( $address ) );
}
} app/Utils/Tags.php 0000644 00000011364 15172727770 0010057 0 ustar 00 <?php
namespace AIOSEO\Plugin\Addon\LocalBusiness\Utils;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Replaces tags with their respective values.
*
* @since 1.1.0
*/
class Tags {
/**
* The tag values that we support.
*
* @since 1.1.0
*
* @var array
*/
private $tags = [];
/**
* The contexts to separate tags.
*
* @since 1.1.0
*
* @var array
*/
private $context = [
'addressFormat' => [
'streetLineOne',
'streetLineTwo',
'zipCode',
'city',
'state',
'country',
'newLine'
]
];
/**
* The address data object.
*
* @since 1.1.0
*
* @var object
*/
private $address;
/**
* Class constructor.
*
* @since 1.1.0
*/
public function __construct() {
add_action( 'init', [ $this, 'init' ] );
}
/**
* Init the tags later to allow filters to be registered and run.
*
* @since 1.1.0
*
* @return void
*/
public function init() {
aioseo()->tags->addContext( $this->context );
$this->tags = [
[
'id' => 'streetLineOne',
'name' => __( 'Address Line 1', 'aioseo-local-business' ),
'description' => __( 'Your Address Line 1', 'aioseo-local-business' ),
'context' => [ 'addressFormat' ]
],
[
'id' => 'streetLineTwo',
'name' => __( 'Address Line 2', 'aioseo-local-business' ),
'description' => __( 'Your Address Line 2', 'aioseo-local-business' ),
'context' => [ 'addressFormat' ]
],
[
'id' => 'zipCode',
'name' => __( 'Zip Code', 'aioseo-local-business' ),
'description' => __( 'Your Zip Code', 'aioseo-local-business' ),
'context' => [ 'addressFormat' ]
],
[
'id' => 'city',
'name' => __( 'City', 'aioseo-local-business' ),
'description' => __( 'Your City', 'aioseo-local-business' ),
'context' => [ 'addressFormat' ]
],
[
'id' => 'state',
'name' => __( 'State', 'aioseo-local-business' ),
'description' => __( 'Your State', 'aioseo-local-business' ),
'context' => [ 'addressFormat' ]
],
[
'id' => 'country',
'name' => __( 'Country', 'aioseo-local-business' ),
'description' => __( 'Your Country', 'aioseo-local-business' ),
'context' => [ 'addressFormat' ]
]
];
$this->tags = apply_filters( 'aioseo_local_business_address_tags', $this->tags );
aioseo()->tags->addTags( $this->tags );
}
/**
* Replace the tags in the string provided.
*
* @since 1.1.0
*
* @param string $string The string with tags.
* @param int $id The page or post ID.
* @param object $addressObject A data object to run the tags against.
* @return string The string with tags replaced.
*/
public function replaceTags( $string, $id, $addressObject = null ) {
if ( ! $string || ! preg_match( '/#/', $string ) ) {
return $string;
}
if ( $addressObject ) {
$this->address = $addressObject;
} else {
if ( 'global' === $id ) {
$this->address = aioseoLocalBusiness()->helpers->getLocalBusinessOptions();
} else {
$this->address = aioseoLocalBusiness()->locations->getLocation( $id );
}
if ( empty( $this->address->locations->business->address ) ) {
return $string;
}
$this->address = $this->address->locations->business->address;
}
$lines = preg_split( '/\r\n|\n|\r/', $string );
foreach ( $lines as $lineKey => &$line ) {
foreach ( $this->tags as $tag ) {
$tagId = aioseo()->tags->denotationChar . $tag['id'];
$pattern = "/$tagId(?![a-zA-Z0-9_])/im";
if ( preg_match( $pattern, $line ) ) {
$line = trim( preg_replace( $pattern, $this->getTagValue( $tag, $id ), $line ) );
if ( empty( $line ) ) {
unset( $lines[ $lineKey ] );
}
}
}
}
$string = implode( PHP_EOL, $lines );
return aioseo()->tags->replaceTags( $string, $id );
}
/**
* Get the value of the tag to replace.
*
* @since 1.1.0
*
* @param array $tag The tag to look for.
* @param int $id The page or post ID.
* @return string The value of the tag.
*/
public function getTagValue( $tag, $id ) {
$tagValue = '';
if ( ! empty( $this->address->{$tag['id']} ) ) {
$tagValue = $this->address->{$tag['id']};
if ( 'country' === $tag['id'] ) {
$tagValue = aioseo()->helpers->getCountryName( $this->address->{$tag['id']} );
}
}
if ( empty( $tagValue ) ) {
switch ( $tag['id'] ) {
case 'streetLineOne':
$tagValue = $this->address->streetLine1;
break;
case 'streetLineTwo':
$tagValue = $this->address->streetLine2;
break;
default:
$tagValue = aioseo()->tags->getTagValue( $tag, $id );
break;
}
}
return apply_filters( 'aioseo_local_business_address_tag_value', $tagValue, $tag, $id );
}
} app/Import/Notifications.php 0000644 00000015673 15172727770 0012153 0 ustar 00 <?php
namespace AIOSEO\Plugin\Addon\LocalBusiness\Import;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
use AIOSEO\Plugin\Common\Models;
class Notifications {
/**
* The notifications.
*
* @since 1.3.0
*
* @var array
*/
private static $notifications = [];
/**
* Class constructor.
*
* @since 1.3.0
*/
public function __construct() {
add_action( 'aioseo_local_seo_imported', [ $this, 'pushNotifications' ] );
}
/**
* Adds a notification.
*
* @since 1.3.0
*
* @param array $args The notification arguments from Models\Notification.
* @return void
*/
public function addNotification( $args ) {
$notificationName = 'local-business-' . md5( $args['title'] );
if ( ! empty( self::$notifications[ $notificationName ] ) ) {
return;
}
self::$notifications[ $notificationName ] = array_merge( [
'slug' => uniqid(),
'notification_name' => $notificationName,
'type' => 'warning',
'level' => [ 'all' ],
'start' => gmdate( 'Y-m-d H:i:s' )
], $args );
}
/**
* Adds a notification for the user to re-enter the business type.
*
* @since 1.3.0
*
* @param string $businessType The business type.
* @return void
*/
public function businessTypeNotSupported( $businessType ) {
$this->addNotification( [
'title' => __( 'Re-Enter Business Type in Local Business', 'aioseo-local-business' ),
'content' => sprintf(
// Translators: 1 - The country.
__( 'For technical reasons, we were unable to migrate the business type you entered for your Local Business schema markup.
Please enter it (%1$s) again by using the dropdown menu.', 'aioseo-local-business' ),
"<strong>$businessType</strong>"
),
'button1_label' => __( 'Fix Now', 'aioseo-local-business' ),
'button1_action' => 'http://route#aioseo-local-seo&aioseo-scroll=info-business-type&aioseo-highlight=info-business-type:locations',
'button2_label' => __( 'Remind Me Later', 'aioseo-local-business' ),
'button2_action' => 'http://action#notification/import-local-business-type-reminder'
] );
}
/**
* Adds a notification for the user to re-enter the country.
*
* @since 1.3.0
*
* @param string $country The country.
* @return void
*/
public function countryNotSupported( $country ) {
$this->addNotification( [
'title' => __( 'Re-Enter Country in Local Business', 'aioseo-local-business' ),
'content' => sprintf(
// Translators: 1 - The country.
__( 'For technical reasons, we were unable to migrate the country you entered for your Local Business schema markup.
Please enter it (%1$s) again by using the dropdown menu.', 'aioseo-local-business' ),
"<strong>$country</strong>"
),
'button1_label' => __( 'Fix Now', 'aioseo-local-business' ),
'button1_action' => 'http://route#aioseo-local-seo&aioseo-scroll=info-business-address-row&aioseo-highlight=aioseo-local-business-business-country:business-info',
'button2_label' => __( 'Remind Me Later', 'aioseo-local-business' ),
'button2_action' => 'http://action#notification/import-local-business-country-reminder'
] );
}
/**
* Adds a notification for the user to re-enter the phone number.
*
* @since 1.3.0
*
* @param string $phoneNumber The phone number.
* @return void
*/
public function phoneNumberNotSupported( $phoneNumber ) {
$this->addNotification( [
'title' => __( 'Invalid Phone Number for Local SEO', 'aioseo-local-business' ),
'content' => sprintf(
// Translators: 1 - The phone number.
__( 'The phone number that you previously entered for your Local Business schema markup is invalid.
As it needs to be internationally formatted, please enter it (%1$s) again with the country code, e.g. +1 (555) 555-1234.', 'aioseo-local-business' ),
"<strong>$phoneNumber</strong>"
),
'button1_label' => __( 'Fix Now', 'aioseo-local-business' ),
'button1_action' => 'http://route#aioseo-local-seo&aioseo-scroll=info-business-contact-row&aioseo-highlight=aioseo-local-business-phone-number:business-info',
'button2_label' => __( 'Remind Me Later', 'aioseo-local-business' ),
'button2_action' => 'http://action#notification/import-local-business-number-reminder'
] );
}
/**
* Adds a notification for the user to re-enter the fax number.
*
* @since 1.3.0
*
* @param string $faxNumber The fax number.
* @return void
*/
public function faxNumberNotSupported( $faxNumber ) {
$this->addNotification( [
'title' => __( 'Invalid Fax Number for Local SEO', 'aioseo-local-business' ),
'content' => sprintf(
// Translators: 1 - The fax number.
__( 'The fax number that you previously entered for your Local Business schema markup is invalid.
As it needs to be internationally formatted, please enter it (%1$s) again with the country code, e.g. +1 (555) 555-1234.', 'aioseo-local-business' ),
"<strong>$faxNumber</strong>"
),
'button1_label' => __( 'Fix Now', 'aioseo-local-business' ),
'button1_action' => 'http://route#aioseo-local-seo&aioseo-scroll=info-business-contact-row&aioseo-highlight=aioseo-local-business-fax-number:business-info',
'button2_label' => __( 'Remind Me Later', 'aioseo-local-business' ),
'button2_action' => 'http://action#notification/import-local-business-fax-reminder'
] );
}
/**
* Adds a notification for the user to re-enter the currencies.
*
* @since 1.3.0
*
* @param array $currencies The currencies.
* @return void
*/
public function currenciesNotSupported( $currencies = [] ) {
$currenciesList = '<ul>';
foreach ( $currencies as $currency ) {
$currenciesList .= '<li>' . esc_html( $currency ) . '<li>';
}
$currenciesList .= '</ul>';
$this->addNotification( [
'title' => __( 'Invalid Currencies for Local SEO', 'aioseo-local-business' ),
'content' => sprintf(
// Translators: 1 - The phone number.
__( 'One or more currencies that you previously entered for your Local Business schema markup are invalid.
Please select these again using our dropdown menu.</br>%1$s', 'aioseo-local-business' ),
"<strong>$currenciesList</strong>"
),
'button1_label' => __( 'Fix Now', 'aioseo-local-business' ),
'button1_action' => 'http://route#aioseo-local-seo&aioseo-scroll=info-payment-info-row&aioseo-highlight=aioseo-local-business-currencies-accepted:business-info',
'button2_label' => __( 'Remind Me Later', 'aioseo-local-business' ),
'button2_action' => 'http://action#notification/import-local-business-currencies-reminder'
] );
}
/**
* Pushes notifications to AIOSEO notifications.
*
* @since 1.3.0
*
* @return void
*/
public function pushNotifications() {
foreach ( self::$notifications as $notification ) {
$exists = Models\Notification::getNotificationByName( $notification['notification_name'] );
if ( $exists->exists() ) {
return;
}
Models\Notification::addNotification( $notification );
}
self::$notifications = [];
}
} app/Import/Helpers.php 0000644 00000040716 15172727770 0010740 0 ustar 00 <?php
namespace AIOSEO\Plugin\Addon\LocalBusiness\Import;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Migrates the Local Business settings from other plugins.
*
* @since 4.0.0
* @version 1.3.0 Moved from Pro.
*/
class Helpers extends \AIOSEO\Plugin\Common\ImportExport\Helpers {
/**
* The error notifications class.
*
* @since 1.3.0
*
* @var Notifications
*/
protected $notifications = null;
/**
* Constructor.
*
* @since 1.3.0
*/
public function __construct() {
$this->notifications = new Notifications();
}
/**
* Migrates the Local Business type.
*
* @since 4.0.0
* @version 1.3.0 Moved from Pro.
*
* @param string $businessType The business type.
* @return bool Whether the business type was imported.
*/
protected function importLocalBusinessType( $businessType ) {
if ( ! $this->validateLocalBusinessType( $businessType ) ) {
return false;
}
aioseo()->options->localBusiness->locations->business->businessType = $businessType;
return true;
}
/**
* Validates the Local Business type.
*
* @since 1.3.0
*
* @param string $businessType The business type.
* @return bool Whether the business type is valid.
*/
protected function validateLocalBusinessType( $businessType ) {
if ( ! $businessType ) {
return false;
}
if ( ! in_array( $businessType, $this->getLocalBusinessTypes(), true ) ) {
$this->notifications->businessTypeNotSupported( $businessType );
return false;
}
return true;
}
/**
* Migrates the Local Business country.
*
* @since 4.0.0
* @version 1.3.0 Moved from Pro.
*
* @param string $country The country.
* @return void
*/
protected function importLocalBusinessCountry( $country ) {
if ( empty( $country ) ) {
return;
}
$found = false;
$country = strtoupper( $country );
foreach ( \AIOSEO\Plugin\Pro\Migration\LocalBusiness::getSupportedCountries() as $countryCode => $countryName ) {
if ( $countryCode === $country || strtoupper( $countryName ) === $country ) {
$found = true;
$country = $countryCode;
break;
}
}
if ( ! $found ) {
$this->notifications->countryNotSupported( $country );
return;
}
aioseo()->options->localBusiness->locations->business->address->country = $country;
}
/**
* Imports the Local Business phone number.
*
* @since 4.0.0
* @version 1.3.0 Moved from Pro.
*
* @param string $phoneNumber The phone number.
* @return void
*/
protected function importLocalBusinessPhoneNumber( $phoneNumber ) {
if ( empty( $phoneNumber ) ) {
return;
}
// Format the phone number.
$phoneNumber = preg_replace( '/[^0-9+]/', '', $phoneNumber );
if ( ! preg_match( '#^\+\d+#', $phoneNumber ) ) {
$this->notifications->phoneNumberNotSupported( $phoneNumber );
return;
}
aioseo()->options->localBusiness->locations->business->contact->phone = $phoneNumber;
}
/**
* Imports the Local Business fax number.
*
* @since 4.0.0
* @version 1.3.0 Moved from Pro.
*
* @return void
*/
protected function importLocalBusinessFaxNumber( $faxNumber ) {
if ( empty( $faxNumber ) ) {
return;
}
// Format the fax number.
$faxNumber = preg_replace( '/[^0-9+]/', '', $faxNumber );
if ( ! preg_match( '#^\+\d+#', $faxNumber ) ) {
$this->notifications->faxNumberNotSupported( $faxNumber );
return;
}
aioseo()->options->localBusiness->locations->business->contact->fax = $faxNumber;
}
/**
* Imports the Local Business accepted currencies.
*
* @since 4.0.0
* @version 1.3.0 Moved from Pro.
*
* @param array $currencies The currencies.
* @return void
*/
protected function importCurrencies( $currencies ) {
$currencies = $this->formatCurrencies( $currencies );
if ( empty( $currencies ) ) {
return;
}
aioseo()->options->localBusiness->locations->business->payment->currenciesAccepted = wp_json_encode( $currencies['supported'] );
if ( count( $currencies['unsupported'] ) ) {
$this->notifications->currenciesNotSupported( $currencies['unsupported'] );
}
}
/**
* Formats Yoast currencies to AIOSEO currencies.
*
* @since 1.3.0
*
* @param array $currencies The currencies array.
* @return array The formatted currencies.
*/
protected function formatCurrencies( $currencies ) {
$supported = [];
if ( empty( $currencies ) ) {
return $supported;
}
$dropdownCurrencies = json_decode( $this->getLocalBusinessCurrencies(), true );
$unsupported = [];
foreach ( $currencies as $currency ) {
$currency = strtoupper( trim( $currency ) );
$found = false;
foreach ( $dropdownCurrencies as $dropdownCurrency ) {
if ( $currency === $dropdownCurrency['value'] ) {
$supported[] = $dropdownCurrency;
$found = true;
break;
}
}
if ( ! $found ) {
$unsupported[] = $currency;
}
}
return [
'supported' => $supported,
'unsupported' => $unsupported
];
}
/**
* Returns our supported Local Business types.
*
* @since 4.0.0
* @version 1.3.0 Moved from Pro.
*
* @return array The list of supported business types.
*/
protected function getLocalBusinessTypes() {
return [
'LocalBusiness',
'AnimalShelter',
'ArchiveOrganization',
'AutomotiveBusiness',
'ChildCare',
'Dentist',
'DryCleaningOrLaundry',
'EmergencyService',
'EmploymentAgency',
'EntertainmentBusiness',
'FinancialService',
'FoodEstablishment',
'GovernmentOffice',
'HealthAndBeautyBusiness',
'HomeAndConstructionBusiness',
'InternetCafe',
'LegalService',
'Library',
'LodgingBusiness',
'MedicalBusiness',
'RadioStation',
'RealEstateAgent',
'RecyclingCenter',
'SelfStorage',
'ShoppingCenter',
'SportsActivityLocation',
'Store',
'TelevisionStation',
'TouristInformationCenter',
'TravelAgency'
];
}
/**
* Returns our supported Local Business currencies.
*
* @since 4.0.0
* @version 1.3.0 Moved from Pro.
*
* @return array The list of supported currencies in JSON.
*/
protected function getLocalBusinessCurrencies() {
return '[{ "symbol": "$", "label": "US Dollar", "value": "USD" },
{ "symbol": "CA$", "label": "Canadian Dollar", "value": "CAD" },
{ "symbol": "€", "label": "Euro", "value": "EUR" },
{ "symbol": "Ƀ", "label": "Bitcoin", "value": "BTC" },
{ "symbol": "AED", "label": "United Arab Emirates Dirham", "value": "AED" },
{ "symbol": "Af", "label": "Afghan Afghani", "value": "AFN" },
{ "symbol": "ALL", "label": "Albanian Lek", "value": "ALL" },
{ "symbol": "AMD", "label": "Armenian Dram", "value": "AMD" },
{ "symbol": "AR$", "label": "Argentine Peso", "value": "ARS" },
{ "symbol": "AU$", "label": "Australian Dollar", "value": "AUD" },
{ "symbol": "man.", "label": "Azerbaijani Manat", "value": "AZN" },
{ "symbol": "KM", "label": "Bosnia-Herzegovina Convertible Mark", "value": "BAM" },
{ "symbol": "Tk", "label": "Bangladeshi Taka", "value": "BDT" },
{ "symbol": "BGN", "label": "Bulgarian Lev", "value": "BGN" },
{ "symbol": "BD", "label": "Bahraini Dinar", "value": "BHD" },
{ "symbol": "FBu", "label": "Burundian Franc", "value": "BIF" },
{ "symbol": "BN$", "label": "Brunei Dollar", "value": "BND" },
{ "symbol": "Bs", "label": "Bolivian Boliviano", "value": "BOB" },
{ "symbol": "R$", "label": "Brazilian Real", "value": "BRL" },
{ "symbol": "BWP", "label": "Botswanan Pula", "value": "BWP" },
{ "symbol": "Br", "label": "Belarusian Ruble", "value": "BYN" },
{ "symbol": "BZ$", "label": "Belize Dollar", "value": "BZD" },
{ "symbol": "CDF", "label": "Congolese Franc", "value": "CDF" },
{ "symbol": "CHF", "label": "Swiss Franc", "value": "CHF" },
{ "symbol": "CL$", "label": "Chilean Peso", "value": "CLP" },
{ "symbol": "CN¥", "label": "Chinese Yuan", "value": "CNY" },
{ "symbol": "CO$", "label": "Colombian Peso", "value": "COP" },
{ "symbol": "₡", "label": "Costa Rican Colón", "value": "CRC" },
{ "symbol": "CV$", "label": "Cape Verdean Escudo", "value": "CVE" },
{ "symbol": "Kč", "label": "Czech Republic Koruna", "value": "CZK" },
{ "symbol": "Fdj", "label": "Djiboutian Franc", "value": "DJF" },
{ "symbol": "Dkr", "label": "Danish Krone", "value": "DKK" },
{ "symbol": "RD$", "label": "Dominican Peso", "value": "DOP" },
{ "symbol": "DA", "label": "Algerian Dinar", "value": "DZD" },
{ "symbol": "Ekr", "label": "Estonian Kroon", "value": "EEK" },
{ "symbol": "EGP", "label": "Egyptian Pound", "value": "EGP" },
{ "symbol": "Nfk", "label": "Eritrean Nakfa", "value": "ERN" },
{ "symbol": "Br", "label": "Ethiopian Birr", "value": "ETB" },
{ "symbol": "£", "label": "British Pound Sterling", "value": "GBP" },
{ "symbol": "GEL", "label": "Georgian Lari", "value": "GEL" },
{ "symbol": "GH₵", "label": "Ghanaian Cedi", "value": "GHS" },
{ "symbol": "FG", "label": "Guinean Franc", "value": "GNF" },
{ "symbol": "GTQ", "label": "Guatemalan Quetzal", "value": "GTQ" },
{ "symbol": "HK$", "label": "Hong Kong Dollar", "value": "HKD" },
{ "symbol": "HNL", "label": "Honduran Lempira", "value": "HNL" },
{ "symbol": "kn", "label": "Croatian Kuna", "value": "HRK" },
{ "symbol": "Ft", "label": "Hungarian Forint", "value": "HUF" },
{ "symbol": "Rp", "label": "Indonesian Rupiah", "value": "IDR" },
{ "symbol": "₪", "label": "Israeli New Sheqel", "value": "ILS" },
{ "symbol": "Rs", "label": "Indian Rupee", "value": "INR" },
{ "symbol": "IQD", "label": "Iraqi Dinar", "value": "IQD" },
{ "symbol": "IRR", "label": "Iranian Rial", "value": "IRR" },
{ "symbol": "Ikr", "label": "Icelandic Króna", "value": "ISK" },
{ "symbol": "J$", "label": "Jamaican Dollar", "value": "JMD" },
{ "symbol": "JD", "label": "Jordanian Dinar", "value": "JOD" },
{ "symbol": "¥", "label": "Japanese Yen", "value": "JPY" },
{ "symbol": "Ksh", "label": "Kenyan Shilling", "value": "KES" },
{ "symbol": "KHR", "label": "Cambodian Riel", "value": "KHR" },
{ "symbol": "CF", "label": "Comorian Franc", "value": "KMF" },
{ "symbol": "₩", "label": "South Korean Won", "value": "KRW" },
{ "symbol": "KD", "label": "Kuwaiti Dinar", "value": "KWD" },
{ "symbol": "KZT", "label": "Kazakhstani Tenge", "value": "KZT" },
{ "symbol": "LB£", "label": "Lebanese Pound", "value": "LBP" },
{ "symbol": "SLRs", "label": "Sri Lankan Rupee", "value": "LKR" },
{ "symbol": "Lt", "label": "Lithuanian Litas", "value": "LTL" },
{ "symbol": "Ls", "label": "Latvian Lats", "value": "LVL" },
{ "symbol": "LD", "label": "Libyan Dinar", "value": "LYD" },
{ "symbol": "MAD", "label": "Moroccan Dirham", "value": "MAD" },
{ "symbol": "MDL", "label": "Moldovan Leu", "value": "MDL" },
{ "symbol": "MGA", "label": "Malagasy Ariary", "value": "MGA" },
{ "symbol": "MKD", "label": "Macedonian Denar", "value": "MKD" },
{ "symbol": "MMK", "label": "Myanma Kyat", "value": "MMK" },
{ "symbol": "MOP$", "label": "Macanese Pataca", "value": "MOP" },
{ "symbol": "MURs", "label": "Mauritian Rupee", "value": "MUR" },
{ "symbol": "MX$", "label": "Mexican Peso", "value": "MXN" },
{ "symbol": "RM", "label": "Malaysian Ringgit", "value": "MYR" },
{ "symbol": "MTn", "label": "Mozambican Metical", "value": "MZN" },
{ "symbol": "N$", "label": "Namibian Dollar", "value": "NAD" },
{ "symbol": "₦", "label": "Nigerian Naira", "value": "NGN" },
{ "symbol": "C$", "label": "Nicaraguan Córdoba", "value": "NIO" },
{ "symbol": "Nkr", "label": "Norwegian Krone", "value": "NOK" },
{ "symbol": "NPRs", "label": "Nepalese Rupee", "value": "NPR" },
{ "symbol": "NZ$", "label": "New Zealand Dollar", "value": "NZD" },
{ "symbol": "OMR", "label": "Omani Rial", "value": "OMR" },
{ "symbol": "B/.", "label": "Panamanian Balboa", "value": "PAB" },
{ "symbol": "S/.", "label": "Peruvian Nuevo Sol", "value": "PEN" },
{ "symbol": "₱", "label": "Philippine Peso", "value": "PHP" },
{ "symbol": "PKRs", "label": "Pakistani Rupee", "value": "PKR" },
{ "symbol": "zł", "label": "Polish Zloty", "value": "PLN" },
{ "symbol": "₲", "label": "Paraguayan Guarani", "value": "PYG" },
{ "symbol": "QR", "label": "Qatari Rial", "value": "QAR" },
{ "symbol": "RON", "label": "Romanian Leu", "value": "RON" },
{ "symbol": "din.", "label": "Serbian Dinar", "value": "RSD" },
{ "symbol": "RUB", "label": "Russian Ruble", "value": "RUB" },
{ "symbol": "RWF", "label": "Rwandan Franc", "value": "RWF" },
{ "symbol": "SR", "label": "Saudi Riyal", "value": "SAR" },
{ "symbol": "SDG", "label": "Sudanese Pound", "value": "SDG" },
{ "symbol": "Skr", "label": "Swedish Krona", "value": "SEK" },
{ "symbol": "S$", "label": "Singapore Dollar", "value": "SGD" },
{ "symbol": "Ssh", "label": "Somali Shilling", "value": "SOS" },
{ "symbol": "SY£", "label": "Syrian Pound", "value": "SYP" },
{ "symbol": "฿", "label": "Thai Baht", "value": "THB" },
{ "symbol": "DT", "label": "Tunisian Dinar", "value": "TND" },
{ "symbol": "T$", "label": "Tongan Paʻanga", "value": "TOP" },
{ "symbol": "TL", "label": "Turkish Lira", "value": "TRY" },
{ "symbol": "TT$", "label": "Trinidad and Tobago Dollar", "value": "TTD" },
{ "symbol": "NT$", "label": "New Taiwan Dollar", "value": "TWD" },
{ "symbol": "TSh", "label": "Tanzanian Shilling", "value": "TZS" },
{ "symbol": "₴", "label": "Ukrainian Hryvnia", "value": "UAH" },
{ "symbol": "USh", "label": "Ugandan Shilling", "value": "UGX" },
{ "symbol": "$U", "label": "Uruguayan Peso", "value": "UYU" },
{ "symbol": "UZS", "label": "Uzbekistan Som", "value": "UZS" },
{ "symbol": "Bs.F.", "label": "Venezuelan Bolívar", "value": "VEF" },
{ "symbol": "₫", "label": "Vietnamese Dong", "value": "VND" },
{ "symbol": "FCFA", "label": "CFA Franc BEAC", "value": "XAF" },
{ "symbol": "CFA", "label": "CFA Franc BCEAO", "value": "XOF" },
{ "symbol": "YR", "label": "Yemeni Rial", "value": "YER" },
{ "symbol": "R", "label": "South African Rand", "value": "ZAR" },
{ "symbol": "ZK", "label": "Zambian Kwacha", "value": "ZMK" },
{ "symbol": "ZWL$", "label": "Zimbabwean Dollar", "value": "ZWL" }]';
}
/**
* Prepare Price Range value.
*
* @since 4.1.3
* @version 1.3.0 Moved from Pro.
*
* @param string $priceRange The price range to prepare.
* @return string The prepared price range.
*/
protected function preparePriceRange( $priceRange ) {
$count = strlen( trim( $priceRange ) );
if ( 0 === $count ) {
return '';
}
if ( 5 < $count ) {
$count = 5;
}
return str_repeat( '$', $count );
}
/**
* Placeholder method.
*
* @since 1.3.0
*
* @param string $value
* @return string
*/
public function macrosToSmartTags( $value ) {
return $value;
}
/**
* Import all the terms of a custom location taxonomy to AIOSEO's taxonomy.
*
* @since 1.3.0
*
* @param string $taxonomy The taxonomy name.
* @return array The imported terms.
*/
protected function importTaxonomyTerms( $taxonomy ) {
$locationCategories = get_terms( [
'taxonomy' => $taxonomy,
'hide_empty' => false
] );
// The taxonomy probably doesn't exist.
if ( is_wp_error( $locationCategories ) ) {
return [];
}
$importedCategories = [];
foreach ( $locationCategories as $locationCategory ) {
$importedCategories[ $locationCategory->term_id ] = $this->importLocationCategory( $locationCategory );
}
// Fix parent reference.
foreach ( $importedCategories as &$importedCategory ) {
if ( ! empty( $importedCategory->oldParentId ) ) {
$newParentId = $importedCategories[ $importedCategory->oldParentId ]->term_id;
if ( $newParentId !== $importedCategory->parent ) {
$importedCategory->parent = $newParentId;
wp_update_term( $importedCategory->term_id, $importedCategory->taxonomy, [ 'parent' => $importedCategory->parent ] );
}
}
}
return $importedCategories;
}
/**
* Import a location category.
*
* @since 1.3.0
*
* @param \WP_Term $locationCategory The location category to import.
* @return \WP_Term The imported location category.
*/
private function importLocationCategory( $locationCategory ) {
$term = get_term_by( 'slug', $locationCategory->slug, aioseoLocalBusiness()->taxonomy->getName() );
if ( ! $term ) {
$term = wp_insert_term( $locationCategory->name, aioseoLocalBusiness()->taxonomy->getName(), [
'description' => $locationCategory->description,
'slug' => $locationCategory->slug
] );
// Return new \WP_Term object.
$term = get_term( $term['term_id'], aioseoLocalBusiness()->taxonomy->getName() );
}
// Reference old id to fix parent-child relationships.
$term->oldParentId = $locationCategory->parent; /** @phpstan-ignore-line */
return $term;
}
} app/Import/Plugins/SeoPress.php 0000644 00000014076 15172727770 0012522 0 ustar 00 <?php
namespace AIOSEO\Plugin\Addon\LocalBusiness\Import\Plugins;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
use AIOSEO\Plugin\Addon\LocalBusiness\Import;
/**
* Imports the Local Business settings.
*
* @since 4.1.4
* @version 1.3.0 Moved from Pro.
*/
class SeoPress extends Import\Importer {
/**
* List of options.
*
* @since 4.1.4
* @version 1.3.0 Moved from Pro.
*
* @var array
*/
private $options = [];
/**
* A list of plugins to look for to import.
*
* @since 1.3.0
*
* @var array
*/
public $plugins = [
[
'name' => 'SEOPress PRO',
'version' => '4.0',
'basename' => 'wp-seopress-pro/seopress-pro.php',
'slug' => 'seopress-pro'
]
];
/**
* Import.
*
* @since 4.1.4
* @version 1.3.0 Moved from Pro.
*
*/
public function doImport() {
$this->options = get_option( 'seopress_pro_option_name' );
if ( empty( $this->options ) ) {
return;
}
if ( ! empty( $this->options['seopress_local_business_type'] ) ) {
$this->importLocalBusinessType( $this->options['seopress_local_business_type'] );
}
$this->importLocalBusinessAddress();
$this->importLocalBusinessPriceRange();
$this->importOpeningHourSettings();
$this->importMapSettings();
}
/**
* Imports the Local Business price range.
*
* @since 4.1.4
* @version 1.3.0 Moved from Pro.
*
* @return void
*/
private function importLocalBusinessPriceRange() {
if ( empty( $this->options['seopress_local_business_price_range'] ) ) {
return;
}
$priceRange = $this->preparePriceRange( $this->options['seopress_local_business_price_range'] );
if ( empty( $priceRange ) ) {
return;
}
aioseo()->options->localBusiness->locations->business->payment->priceRange = $priceRange;
}
/**
* Imports the Local Business address.
*
* @since 4.1.4
* @version 1.3.0 Moved from Pro.
*
* @return void
*/
private function importLocalBusinessAddress() {
if ( ! empty( $this->options['seopress_local_business_address_country'] ) ) {
$this->importLocalBusinessCountry( $this->options['seopress_local_business_address_country'] );
}
$settings = [
'seopress_local_business_street_address' => [
'type' => 'string',
'newOption' => [ 'localBusiness', 'locations', 'business', 'address', 'streetLine1' ]
],
'seopress_local_business_address_locality' => [
'type' => 'string',
'newOption' => [ 'localBusiness', 'locations', 'business', 'address', 'city' ]
],
'seopress_local_business_address_region' => [
'type' => 'string',
'newOption' => [ 'localBusiness', 'locations', 'business', 'address', 'state' ]
],
'seopress_local_business_postal_code' => [
'type' => 'string',
'newOption' => [ 'localBusiness', 'locations', 'business', 'address', 'zipCode' ]
],
'seopress_local_business_phone' => [
'type' => 'string',
'newOption' => [ 'localBusiness', 'locations', 'business', 'contact', 'phone' ]
],
];
$this->mapOldToNew( $settings, $this->options );
}
/**
* Imports the Local Business Opening Hours settings.
*
* @since 4.1.4
* @version 1.3.0 Moved from Pro.
*
* @return void
*/
private function importOpeningHourSettings() {
$openingHours = $this->options['seopress_local_business_opening_hours'];
if ( empty( $openingHours ) ) {
return;
}
aioseo()->options->localBusiness->openingHours->use24hFormat = true;
$days = [ 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday' ];
foreach ( $openingHours as $key => $settings ) {
if ( ! aioseo()->options->localBusiness->openingHours->days->has( $days[ $key ] ) ) {
continue;
}
// Reset some defaults.
aioseo()->options->localBusiness->openingHours->days->{$days[ $key ]}->closed = false;
aioseo()->options->localBusiness->openingHours->days->{$days[ $key ]}->open24h = false;
// In SEOPress the option is called 'open' but being true means the business is closed.
// That can be seen in the options where the label for the field is "Closed all the day?".
// Also, can be seen in the schema output where it checks if the key exists, which means closed.
if ( ! empty( $settings['open'] ) ) {
aioseo()->options->localBusiness->openingHours->days->{$days[ $key ]}->closed = true;
}
// Closed this day.
if ( empty( $settings['am']['open'] ) && empty( $settings['pm']['open'] ) ) {
aioseo()->options->localBusiness->openingHours->days->{$days[ $key ]}->closed = true;
}
$meridiem = 'am';
$openTime = $settings[ $meridiem ]['start']['hours'] . ':' . $settings[ $meridiem ]['start']['mins'];
// Morning from 00:00 to 23:59 means open 24 hours.
if ( '00:00' === $openTime && '23:59' === $settings[ $meridiem ]['end']['hours'] . ':' . $settings[ $meridiem ]['end']['mins'] ) {
aioseo()->options->localBusiness->openingHours->days->{$days[ $key ]}->open24h = true;
}
if ( ! empty( $settings['pm']['open'] ) ) {
$meridiem = 'pm';
if ( empty( $settings['am']['open'] ) ) {
$openTime = $settings[ $meridiem ]['start']['hours'] . ':' . $settings[ $meridiem ]['start']['mins'];
}
}
$closeTime = $settings[ $meridiem ]['end']['hours'] . ':' . $settings[ $meridiem ]['end']['mins'];
aioseo()->options->localBusiness->openingHours->days->{ $days[ $key ] }->openTime = $openTime;
aioseo()->options->localBusiness->openingHours->days->{ $days[ $key ] }->closeTime = $closeTime;
}
}
/**
* Imports the Local Business map settings.
*
* @since 1.3.0
*
* @return void
*/
private function importMapSettings() {
if ( ! empty( $this->options['seopress_local_business_lat'] ) && ! empty( $this->options['seopress_local_business_lon'] ) ) {
aioseo()->options->localBusiness->maps->mapOptions->center->lat = $this->options['seopress_local_business_lat'];
aioseo()->options->localBusiness->maps->mapOptions->center->lng = $this->options['seopress_local_business_lon'];
}
if ( ! empty( $this->options['seopress_local_business_place_id'] ) ) {
aioseo()->options->localBusiness->maps->placeId = $this->options['seopress_local_business_place_id'];
}
}
} app/Import/Plugins/RankMath.php 0000644 00000013070 15172727770 0012455 0 ustar 00 <?php
namespace AIOSEO\Plugin\Addon\LocalBusiness\Import\Plugins;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
use AIOSEO\Plugin\Addon\LocalBusiness\Import;
/**
* Migrates the Local Business settings.
*
* These are contained in the Title & Meta section of Rank Math.
*
* @since 4.0.0
* @version 1.3.0 Moved from Pro.
*/
class RankMath extends Import\Importer {
/**
* List of options.
*
* @since 4.2.7
* @version 1.3.0 Moved from Pro.
*
* @var array
*/
private $options = [];
/**
* A list of plugins to look for to import.
*
* @since 1.3.0
*
* @var array
*/
public $plugins = [
[
'name' => 'Rank Math SEO',
'version' => '1.0',
'basename' => 'seo-by-rank-math/rank-math.php',
'slug' => 'rank-math-seo'
]
];
/**
* Import.
*
* @since 4.0.0
* @version 1.3.0 Moved from Pro.
*/
public function doImport() {
$this->options = get_option( 'rank-math-options-titles' );
if ( empty( $this->options ) ) {
return;
}
if ( isset( $this->options['local_business_type'] ) ) {
$this->importLocalBusinessType( $this->options['local_business_type'] );
}
if ( ! empty( $this->options['email'] ) ) {
aioseo()->options->localBusiness->locations->business->contact->email = $this->options['email'];
}
$this->importLocalBusinessAddress();
$this->importPhoneNumber();
$this->importLocalBusinessPriceRange();
$this->importOpeningHourSettings();
$this->importMapSettings();
}
/**
* Migrates the Local Business price range.
*
* @since 4.0.0
* @version 1.3.0 Moved from Pro.
*
* @return void
*/
private function importLocalBusinessPriceRange() {
if ( empty( $this->options['price_range'] ) ) {
return;
}
$priceRange = $this->preparePriceRange( $this->options['price_range'] );
if ( empty( $priceRange ) ) {
return;
}
aioseo()->options->localBusiness->locations->business->payment->priceRange = $priceRange;
}
/**
* Migrates the Local Business address.
*
* @since 4.0.0
* @version 1.3.0 Moved from Pro.
*
* @return void
*/
private function importLocalBusinessAddress() {
if ( empty( $this->options['local_address'] ) ) {
return;
}
if ( ! empty( $this->options['local_address']['addressCountry'] ) ) {
$this->importLocalBusinessCountry( $this->options['local_address']['addressCountry'] );
}
$settings = [
'streetAddress' => [
'type' => 'string',
'newOption' => [ 'localBusiness', 'locations', 'business', 'address', 'streetLine1' ]
],
'addressLocality' => [
'type' => 'string',
'newOption' => [ 'localBusiness', 'locations', 'business', 'address', 'city' ]
],
'addressRegion' => [
'type' => 'string',
'newOption' => [ 'localBusiness', 'locations', 'business', 'address', 'state' ]
],
'postalCode' => [
'type' => 'string',
'newOption' => [ 'localBusiness', 'locations', 'business', 'address', 'zipCode' ]
],
];
aioseo()->importExport->rankMath->helpers->mapOldToNew( $settings, $this->options['local_address'] );
}
/**
* Migrates the Local Business opening hour settings.
*
* @since 4.0.0
* @version 1.3.0 Moved from Pro.
*
* @return void
*/
private function importOpeningHourSettings() {
if ( ! empty( $this->options['opening_hours_format'] ) ) {
aioseo()->options->localBusiness->openingHours->use24hFormat = 'off' === $this->options['opening_hours_format'];
}
if ( empty( $this->options['opening_hours'] ) ) {
return;
}
$days = aioseo()->options->localBusiness->openingHours->days->all();
foreach ( $days as $name => $values ) {
aioseo()->options->localBusiness->openingHours->days->$name->closed = true;
$importDay = array_filter( $this->options['opening_hours'], function ( $day ) use ( $name ) {
return strtolower( $day['day'] ) === $name && ! empty( $day['time'] );
} );
$importDay = current( $importDay );
if ( empty( $importDay ) ) {
continue;
}
aioseo()->options->localBusiness->openingHours->days->$name->closed = false;
preg_match( '#^(\d{1,2}:\d{2})-(\d{1,2}:\d{2})$#', $importDay['time'], $matches );
if ( ! empty( $matches[1] ) ) {
aioseo()->options->localBusiness->openingHours->days->$name->openTime = str_pad( $matches[1], 5, '0', STR_PAD_LEFT );
}
if ( ! empty( $matches[2] ) ) {
aioseo()->options->localBusiness->openingHours->days->$name->closeTime = str_pad( $matches[2], 5, '0', STR_PAD_LEFT );
}
if ( '00:00' === $matches[1] && '23:59' === $matches[2] ) {
aioseo()->options->localBusiness->openingHours->days->$name->open24h = true;
}
}
}
/**
* Imports the Local Business map settings.
*
* @since 1.3.0
*
* @return void
*/
private function importMapSettings() {
if ( ! empty( $this->options['maps_api_key'] ) ) {
aioseo()->options->localBusiness->maps->apiKey = $this->options['maps_api_key'];
aioseo()->options->localBusiness->maps->apiKeyValid = true;
}
if ( ! empty( $this->options['geo'] ) ) {
list( $lat, $lng ) = explode( ',', $this->options['geo'] );
aioseo()->options->localBusiness->maps->mapOptions->center->lat = $lat;
aioseo()->options->localBusiness->maps->mapOptions->center->lng = $lng;
}
}
/**
* Imports the phone number.
*
* @since 1.3.0
*
* @return void
*/
private function importPhoneNumber() {
if ( ! is_array( $this->options['phone_numbers'] ) || empty( $this->options['phone_numbers'] ) ) {
return;
}
$phoneNumber = current( $this->options['phone_numbers'] );
if ( ! empty( $phoneNumber['number'] ) ) {
$this->importLocalBusinessPhoneNumber( $phoneNumber['number'] );
}
}
} app/Import/Plugins/YoastSeo.php 0000644 00000036453 15172727770 0012530 0 ustar 00 <?php
namespace AIOSEO\Plugin\Addon\LocalBusiness\Import\Plugins;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
use AIOSEO\Plugin\Common\Models;
use AIOSEO\Plugin\Addon\LocalBusiness\Import;
/**
* The YoastSEO importer class.
*
* @since 4.0.0
* @version 1.3.0 Moved from Pro.
*/
class YoastSeo extends Import\Importer {
/**
* List of options.
*
* @since 4.2.7
* @version 1.3.0 Moved from Pro.
*
* @var array
*/
private $options = [];
/**
* A list of plugins to look for to import.
*
* @since 1.3.0
*
* @var array
*/
public $plugins = [
[
'name' => 'Yoast SEO: Local',
'version' => '14.9',
'basename' => 'wpseo-local/local-seo.php',
'slug' => 'yoast-local-seo'
]
];
/**
* Import.
*
* @since 4.0.0
* @version 1.3.0 Moved from Pro.
*
* @return void
*/
public function doImport() {
$this->options = get_option( 'wpseo_local' );
if ( empty( $this->options ) ) {
return;
}
// Yoast SEO doesn't have a setting for this, so we'll use the Organization Name.
aioseo()->options->localBusiness->locations->business->name = aioseo()->options->searchAppearance->global->schema->organizationName;
if ( ! empty( $this->options['business_type'] ) ) {
$this->importLocalBusinessType( $this->options['business_type'] );
}
if ( ! empty( $this->options['location_country'] ) ) {
$this->importLocalBusinessCountry( $this->options['location_country'] );
}
if ( ! empty( $this->options['location_phone'] ) ) {
$this->importLocalBusinessPhoneNumber( $this->options['location_phone'] );
}
if ( ! empty( $this->options['location_fax'] ) ) {
$this->importLocalBusinessFaxNumber( $this->options['location_fax'] );
}
if ( ! empty( $this->options['location_currencies_accepted'] ) ) {
$currencies = array_filter( explode( ',', $this->options['location_currencies_accepted'] ) );
$this->importCurrencies( $currencies );
}
$settings = [
'location_email' => [
'type' => 'string',
'newOption' => [ 'localBusiness', 'locations', 'business', 'contact', 'email' ]
],
'location_address' => [
'type' => 'string',
'newOption' => [ 'localBusiness', 'locations', 'business', 'address', 'streetLine1' ]
],
'location_address_2' => [
'type' => 'string',
'newOption' => [ 'localBusiness', 'locations', 'business', 'address', 'streetLine2' ]
],
'location_city' => [
'type' => 'string',
'newOption' => [ 'localBusiness', 'locations', 'business', 'address', 'city' ]
],
'location_state' => [
'type' => 'string',
'newOption' => [ 'localBusiness', 'locations', 'business', 'address', 'state' ]
],
'location_zipcode' => [
'type' => 'string',
'newOption' => [ 'localBusiness', 'locations', 'business', 'address', 'zipCode' ]
],
'location_vat_id' => [
'type' => 'string',
'newOption' => [ 'localBusiness', 'locations', 'business', 'ids', 'vat' ]
],
'location_tax_id' => [
'type' => 'string',
'newOption' => [ 'localBusiness', 'locations', 'business', 'ids', 'tax' ]
],
'location_coc_id' => [
'type' => 'string',
'newOption' => [ 'localBusiness', 'locations', 'business', 'ids', 'chamberOfCommerce' ]
],
'location_price_range' => [
'type' => 'string',
'newOption' => [ 'localBusiness', 'locations', 'business', 'payment', 'priceRange' ]
],
'location_payment_accepted' => [
'type' => 'string',
'newOption' => [ 'localBusiness', 'locations', 'business', 'payment', 'methods' ]
],
'location_area_served' => [
'type' => 'string',
'newOption' => [ 'localBusiness', 'locations', 'business', 'areaServed' ]
],
];
$this->mapOldToNew( $settings, $this->options );
$this->importAddressFormat();
$this->importOpeningHourSettings();
$this->importMapSettings();
$this->importMultipleLocations();
}
/**
* Imports the Local Business opening hour settings.
*
* @since 4.0.0
* @version 1.3.0 Moved from Pro.
*
* @return void
*/
private function importOpeningHourSettings() {
if ( ! empty( $this->options['hide_opening_hours'] ) ) {
aioseo()->options->localBusiness->openingHours->show = 'off' === $this->options['hide_opening_hours'];
}
if ( ! empty( $this->options['open_247'] ) ) {
aioseo()->options->localBusiness->openingHours->alwaysOpen = 'on' === $this->options['open_247'];
}
if ( ! empty( $this->options['closed_label'] ) ) {
aioseo()->options->localBusiness->openingHours->labels->closed = $this->options['closed_label'];
}
if ( ! empty( $this->options['open_24h_label'] ) ) {
aioseo()->options->localBusiness->openingHours->labels->alwaysOpen = $this->options['open_24h_label'];
}
if ( ! empty( $this->options['opening_hours_24h'] ) ) {
aioseo()->options->localBusiness->openingHours->use24hFormat = 'on' === $this->options['opening_hours_24h'];
}
$days = $this->formatOpeningHoursDays( $this->options );
foreach ( $days as $day => $dayOptions ) {
foreach ( $dayOptions as $option => $value ) {
aioseo()->options->localBusiness->openingHours->days->$day->$option = $value;
}
}
}
/**
* Formats the opening hours.
*
* @since 1.3.0
*
* @param array $options The options array from Yoast.
* @return array The formatted opening hours.
*/
private function formatOpeningHoursDays( $options ) {
$openingHoursDays = [];
$days = aioseo()->options->localBusiness->openingHours->days->all();
foreach ( $days as $name => $values ) {
if ( ! empty( $options[ "opening_hours_{$name}_24h" ] ) ) {
$openingHoursDays[ $name ]['open24h'] = 'on' === $options[ "opening_hours_{$name}_24h" ];
}
if ( ! empty( $options[ "opening_hours_{$name}_from" ] ) ) {
if ( 'closed' === $options[ "opening_hours_{$name}_from" ] ) {
$openingHoursDays[ $name ]['closed'] = true;
continue;
}
$openingHoursDays[ $name ]['openTime'] = $options[ "opening_hours_{$name}_from" ];
}
if ( ! empty( $options[ "opening_hours_{$name}_to" ] ) ) {
if ( 'closed' === $options[ "opening_hours_{$name}_to" ] ) {
$openingHoursDays[ $name ]['closed'] = true;
continue;
}
$openingHoursDays[ $name ]['closeTime'] = $options[ "opening_hours_{$name}_to" ];
}
}
return $openingHoursDays;
}
/**
* Imports the Address format.
*
* @since 1.3.0
*
* @return void
*/
private function importAddressFormat() {
if ( empty( $this->options['address_format'] ) ) {
return;
}
$formatMap = [
'address-state-postal' => '#streetLineOne #streetLineTwo #city, #state #zipCode',
'address-state-postal-comma' => '#streetLineOne #streetLineTwo #city, #state, #zipCode',
'address-postal-city-state' => '#streetLineOne #streetLineTwo #zipCode #city, #state',
'address-postal' => '#streetLineOne #streetLineTwo #city #zipCode',
'address-postal-comma' => '#streetLineOne #streetLineTwo #city, #zipCode',
'address-city' => '#streetLineOne #streetLineTwo #city',
'postal-address' => '#zipCode #state #city #streetLineOne #streetLineTwo'
];
if ( empty( $formatMap[ $this->options['address_format'] ] ) ) {
return;
}
aioseo()->options->localBusiness->locations->business->address->addressFormat = $formatMap[ $this->options['address_format'] ];
}
/**
* Imports multiple locations.
*
* @since 1.3.0
*
* @return void
*/
private function importMultipleLocations() {
aioseo()->options->localBusiness->locations->general->multiple = ! empty( $this->options['use_multiple_locations'] ) && 'on' === $this->options['use_multiple_locations'];
if ( ! empty( $this->options['locations_label_singular'] ) ) {
aioseo()->options->localBusiness->locations->general->singleLabel = $this->options['locations_label_singular'];
}
if ( ! empty( $this->options['locations_label_plural'] ) ) {
aioseo()->options->localBusiness->locations->general->pluralLabel = $this->options['locations_label_plural'];
}
if ( ! empty( $this->options['locations_slug'] ) ) {
aioseo()->options->localBusiness->locations->general->useCustomSlug = true;
aioseo()->options->localBusiness->locations->general->customSlug = $this->options['locations_slug'];
}
if ( ! empty( $this->options['locations_taxo_slug'] ) ) {
aioseo()->options->localBusiness->locations->general->useCustomCategorySlug = true;
aioseo()->options->localBusiness->locations->general->customCategorySlug = $this->options['locations_taxo_slug'];
}
if ( ! empty( $this->options['local_enhanced_search'] ) && 'on' === $this->options['local_enhanced_search'] ) {
aioseo()->options->localBusiness->locations->general->enhancedSearch = true;
}
if ( aioseo()->options->localBusiness->locations->general->multiple ) {
// Query wpseo-local categories.
$importedCategories = $this->importTaxonomyTerms( 'wpseo_locations_category' );
// Query wpseo-local locations.
$locations = get_posts( [
'post_type' => 'wpseo_locations',
'posts_per_page' => -1,
'post_status' => 'any'
] );
foreach ( $locations as $location ) {
$this->importLocation( $location, $importedCategories );
}
}
}
/**
* Imports a Location.
*
* @since 1.3.0
*
* @param \WP_Post $yoastLocation The location to import.
* @param array $importedCategories The imported categories.
* @return void
*/
private function importLocation( $yoastLocation, $importedCategories ) {
// Get the Yoast meta.
$yoastMetaRaw = get_post_meta( $yoastLocation->ID );
// Filter only needed data.
$yoastMetaRaw = array_filter( $yoastMetaRaw, function ( $key ) {
return 0 === strpos( $key, '_wpseo_' );
}, ARRAY_FILTER_USE_KEY );
// Flatten the Yoast meta.
$yoastMetaRaw = array_map( function ( $n ) {
return $n[0];
}, $yoastMetaRaw );
// Normalize meta.
$yoastMeta = [];
foreach ( $yoastMetaRaw as $key => $value ) {
$yoastMeta[ preg_replace( '%^_wpseo_%', '', $key ) ] = $value;
}
// Location and business data.
$locationData = [
'business_name' => [ 'locations', 'business', 'name' ],
'business_type' => [ 'locations', 'business', 'businessType' ],
'business_location_logo' => [ 'locations', 'business', 'image' ],
'business_address' => [ 'locations', 'business', 'address', 'streetLine1' ],
'business_address_2' => [ 'locations', 'business', 'address', 'streetLine2' ],
'business_city' => [ 'locations', 'business', 'address', 'city' ],
'business_state' => [ 'locations', 'business', 'address', 'state' ],
'business_zipcode' => [ 'locations', 'business', 'address', 'zipCode' ],
'business_country' => [ 'locations', 'business', 'address', 'country' ],
'business_phone' => [ 'locations', 'business', 'contact', 'phone' ],
'business_fax' => [ 'locations', 'business', 'contact', 'fax' ],
'business_email' => [ 'locations', 'business', 'contact', 'email' ],
'business_vat_id' => [ 'locations', 'business', 'ids', 'vat' ],
'business_tax_id' => [ 'locations', 'business', 'ids', 'tax' ],
'business_coc_id' => [ 'locations', 'business', 'ids', 'chamberOfCommerce' ],
'business_price_range' => [ 'locations', 'business', 'payment', 'priceRange' ],
'business_currencies_accepted' => [ 'locations', 'business', 'payment', 'currenciesAccepted' ],
'business_payment_accepted' => [ 'locations', 'business', 'payment', 'methods' ],
'business_area_served' => [ 'locations', 'business', 'areaServed' ]
];
// Create the data array.
$dataArray = [];
foreach ( $locationData as $metaKey => $locationKeys ) {
$metaValue = ! empty( $yoastMeta[ $metaKey ] ) ? $yoastMeta[ $metaKey ] : null;
if ( ! empty( $metaValue ) ) {
// Treat currencies.
if ( 'business_currencies_accepted' === $metaKey ) {
$metaValue = array_filter( explode( ',', $metaValue ) );
$metaValue = $this->formatCurrencies( $metaValue );
if ( ! empty( $metaValue['supported'] ) ) {
$metaValue = wp_json_encode( $metaValue['supported'] );
}
}
$metaValue = aioseo()->helpers->createMultidimensionalArray( $locationKeys, $metaValue );
$dataArray = array_merge_recursive( $dataArray, $metaValue );
}
}
// Opening hours.
$dataArray['openingHours'] = [
'useDefaults' => false,
'show' => true,
'use24hFormat' => 'on' === $yoastMeta['format_24h'],
'alwaysOpen' => 'on' === $yoastMeta['open_247'],
'days' => $this->formatOpeningHoursDays( $yoastMeta )
];
// Maps.
if ( ! empty( $yoastMeta['coordinates_lat'] ) && ! empty( $yoastMeta['coordinates_long'] ) ) {
$dataArray['maps'] = [
'mapOptions' => [
'center' => [
'lat' => $yoastMeta['coordinates_lat'],
'lng' => $yoastMeta['coordinates_long']
]
],
'customMarker' => ! empty( $yoastMeta['business_location_custom_marker'] ) ? $yoastMeta['business_location_custom_marker'] : ''
];
}
// Check if the location already exists.
$wpPost = aioseoLocalBusiness()->locations->getLocationByName( $yoastLocation->post_name );
// Create the location if it doesn't exist.
if ( empty( $wpPost ) ) {
$wpPost = clone $yoastLocation;
$wpPost->ID = null;
$wpPost->post_type = aioseoLocalBusiness()->postType->getName();
$wpPost = wp_insert_post( $wpPost );
$wpPost = get_post( $wpPost );
}
// Set the location categories.
$categories = wp_get_post_terms( $yoastLocation->ID, 'wpseo_locations_category' );
$mappedCategories = [];
foreach ( $categories as $category ) {
if ( ! is_object( $category ) ) {
$category = (object) $category;
}
if ( empty( $category->term_id ) ) {
continue;
}
$importedCategory = ! empty( $importedCategories[ $category->term_id ] ) ? $importedCategories[ $category->term_id ] : null;
if ( $importedCategory ) {
$mappedCategories[] = $importedCategory->term_id;
}
}
wp_set_post_terms( $wpPost->ID, $mappedCategories, aioseoLocalBusiness()->taxonomy->getName() );
// Set AIOSEO's location data.
$aioseoLocation = Models\Post::getPost( $wpPost->ID );
$aioseoLocation->local_seo = $dataArray;
$aioseoLocation->save();
}
/**
* Imports the Local Business map settings.
*
* @since 1.3.0
*
* @return void
*/
private function importMapSettings() {
if ( ! empty( $this->options['googlemaps_api_key'] ) ) {
aioseo()->options->localBusiness->maps->apiKey = $this->options['googlemaps_api_key'];
aioseo()->options->localBusiness->maps->apiKeyValid = true;
}
if ( ! empty( $this->options['map_view_style'] ) ) {
aioseo()->options->localBusiness->maps->mapOptions->mapTypeId = strtolower( $this->options['map_view_style'] );
}
if ( ! empty( $this->options['location_coords_lat'] ) && ! empty( $this->options['location_coords_long'] ) ) {
aioseo()->options->localBusiness->maps->mapOptions->center->lat = $this->options['location_coords_lat'];
aioseo()->options->localBusiness->maps->mapOptions->center->lng = $this->options['location_coords_long'];
}
if ( ! empty( $this->options['local_custom_marker'] ) ) {
aioseo()->options->localBusiness->maps->customMarker = wp_get_attachment_image_url( $this->options['local_custom_marker'], 'full' );
}
}
} app/Import/Importer.php 0000644 00000001254 15172727770 0011131 0 ustar 00 <?php
namespace AIOSEO\Plugin\Addon\LocalBusiness\Import;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Imports local business info from other plugins.
*
* @since 1.3.0
*/
class Importer extends Helpers {
/**
* The list of plugins.
*
* @since 1.3.0
*
* @var array
*/
protected $plugins = [];
/**
* The post action name.
*
* @since 1.3.0
*
* @param Import $importer The main importer class.
*/
public function __construct( $importer ) {
parent::__construct();
$plugins = $this->plugins;
foreach ( $plugins as $key => $plugin ) {
$plugins[ $key ]['class'] = $this;
}
$importer->addPlugins( $plugins );
}
} app/Import/Import.php 0000644 00000004567 15172727770 0010614 0 ustar 00 <?php
namespace AIOSEO\Plugin\Addon\LocalBusiness\Import;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Handles the importing/exporting of settings and SEO data.
*
* @since 1.3.0
*/
class Import {
/**
* Set up an array of plugins for importing.
*
* @since 1.3.0
*
* @var array
*/
private $plugins = [];
/**
* Class constructor.
*
* @since 1.3.0
*/
public function __construct() {
new Plugins\YoastSeo( $this );
new Plugins\SeoPress( $this );
new Plugins\RankMath( $this );
}
/**
* Starts an import.
*
* @since 1.3.0
*
* @param string $plugin The slug of the plugin to import.
* @return void
*/
public function startImport( $plugin ) {
foreach ( $this->plugins as $pluginData ) {
if ( $pluginData['slug'] === $plugin ) {
$pluginData['class']->doImport();
do_action( 'aioseo_local_seo_imported', $plugin );
return;
}
}
}
/**
* Adds plugins to the import.
*
* @since 1.3.0
*
* @param array $plugins The plugins to add.
* @return void
*/
public function addPlugins( $plugins ) {
$this->plugins = array_merge( $this->plugins, $plugins );
}
/**
* Get the plugins we allow importing from.
*
* @since 1.3.0
*
* @return array
*/
public function plugins() {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
$plugins = [];
$installedPlugins = array_keys( get_plugins() );
foreach ( $this->plugins as $importerPlugin ) {
$data = [
'slug' => $importerPlugin['slug'],
'name' => $importerPlugin['name'],
'version' => null,
'canImport' => false,
'basename' => $importerPlugin['basename'],
'installed' => false,
'activated' => false
];
if ( in_array( $importerPlugin['basename'], $installedPlugins, true ) ) {
$pluginData = get_file_data( trailingslashit( WP_PLUGIN_DIR ) . $importerPlugin['basename'], [
'name' => 'Plugin Name',
'version' => 'Version',
] );
$canImport = false;
if ( version_compare( $importerPlugin['version'], $pluginData['version'], '<=' ) ) {
$canImport = true;
}
$data['name'] = $pluginData['name'];
$data['version'] = $pluginData['version'];
$data['canImport'] = $canImport;
$data['installed'] = true;
$data['activated'] = is_plugin_active( $importerPlugin['basename'] );
}
$plugins[] = $data;
}
return $plugins;
}
} app/LocalBusiness.php 0000644 00000024011 15172727770 0010620 0 ustar 00 <?php
namespace AIOSEO\Plugin\Addon\LocalBusiness {
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Main class.
*
* @since 1.0.0
*/
final class LocalBusiness {
/**
* Holds the instance of the plugin currently in use.
*
* @since 1.0.0
*
* @var \AIOSEO\Plugin\Addon\LocalBusiness\LocalBusiness
*/
private static $instance = null;
/**
* Plugin version for enqueueing, etc.
* The value is retrieved from the version constant.
*
* @since 1.0.0
*
* @var string
*/
public $version = '';
/**
* Instance of the Admin class.
*
* @since 1.1.0
*
* @var Admin\Admin
*/
public $admin = null;
/**
* Instance of the Usage class.
*
* @since 1.2.10
*
* @var Admin\Usage
*/
public $usage = null;
/**
* Instance of the Locations class.
*
* @since 1.1.0
*
* @var Locations\Locations
*/
public $locations = null;
/**
* Instance of the Shortcodes class.
*
* @since 1.1.0
*
* @var Shortcodes\Shortcodes
*/
public $shortcodes = null;
/**
* Instance of the Location postType class.
*
* @since 1.1.0
*
* @var Admin\Location
*/
public $postType = null;
/**
* Instance of the Location taxonomy class.
*
* @since 1.1.0
*
* @var Admin\LocationCategory
*/
public $taxonomy = null;
/**
* Instance of the Blocks class containing all blocks.
*
* @since 1.1.0
*
* @var Blocks\Blocks
*/
public $blocks = null;
/**
* Instance of the Widgets class registering all widgets.
*
* @since 1.1.0
*
* @var Widgets\Widgets
*/
public $widgets = null;
/**
* Instance of the Schema class.
*
* @since 1.1.0
*
* @var Schema\Schema
*/
public $schema = null;
/**
* Instance of the Tags class.
*
* @since 1.1.0
*
* @var Utils\Tags
*/
public $tags = null;
/**
* Instance of the Helpers class.
*
* @since 1.1.0
*
* @var Utils\Helpers
*/
public $helpers = null;
/**
* Instance of the Search class.
*
* @since 1.1.0
*
* @var Main\Search
*/
public $search = null;
/**
* Instance of the Templates class.
*
* @since 1.1.0
*
* @var Utils\Templates
*/
public $templates = null;
/**
* Instance of the Access class.
*
* @since 1.1.0
*
* @var Utils\Access
*/
public $access = null;
/**
* Instance of the Activate class.
*
* @since 1.1.0
*
* @var Main\Activate
*/
public $activate = null;
/**
* Instance of the Map class.
*
* @since 1.1.3
*
* @var Locations\Maps
*/
public $maps = null;
/**
* Instance of the API class.
*
* @since 1.1.3
*
* @var Api\Api
*/
public $api = null;
/**
* Whether we're in a dev environment.
*
* @since 1.2.4
*
* @var bool
*/
public $isDev = false;
/**
* Cache class instance.
*
* @since 1.2.12
*
* @var Utils\Cache
*/
public $cache = null;
/**
* Assets class instance.
*
* @since 1.2.12
*
* @var Utils\Assets
*/
public $assets = null;
/**
* InternalOptions class instance.
*
* @since 1.2.12
*
* @var Utils\InternalOptions
*/
public $internalOptions = null;
/**
* Updates class instance.
*
* @since 1.2.12
*
* @var Main\Updates
*/
public $updates = null;
/**
* Import class instance.
*
* @since 1.3.0
*
* @var Import\Import
*/
public $import = null;
/**
* Knowledge Graph Organization graph class instance.
*
* @since 1.3.3
*
* @var Schema\Graphs\KgOrganization
*/
public $kgOrganization;
/**
* Main LocalBusiness Instance.
*
* Insures that only one instance of the addon exists in memory at any one
* time. Also prevents needing to define globals all over the place.
*
* @since 1.0.0
*
* @return \AIOSEO\Plugin\Addon\LocalBusiness\LocalBusiness
*/
public static function instance() {
if ( null === self::$instance || ! self::$instance instanceof self ) {
self::$instance = new self();
self::$instance->constants();
self::$instance->includes();
self::$instance->load();
add_action( 'init', [ self::$instance, 'registerStyles' ] );
}
return self::$instance;
}
/**
* Setup plugin constants.
* All the path/URL related constants are defined in main plugin file.
*
* @since 1.0.0
*
* @return void
*/
private function constants() {
$defaultHeaders = [
'name' => 'Plugin Name',
'version' => 'Version',
];
$pluginData = get_file_data( AIOSEO_LOCAL_BUSINESS_FILE, $defaultHeaders );
$constants = [
'AIOSEO_LOCAL_BUSINESS_VERSION' => $pluginData['version']
];
foreach ( $constants as $constant => $value ) {
if ( ! defined( $constant ) ) {
define( $constant, $value );
}
}
$this->version = AIOSEO_LOCAL_BUSINESS_VERSION;
}
/**
* Including the new files with PHP 5.3 style.
*
* @since 1.0.0
*
* @return void
*/
private function includes() {
$dependencies = [
'/vendor/autoload.php'
];
foreach ( $dependencies as $path ) {
if ( ! file_exists( AIOSEO_LOCAL_BUSINESS_DIR . $path ) ) {
// Something is not right.
status_header( 500 );
wp_die( esc_html__( 'Plugin is missing required dependencies. Please contact support for more information.', 'aioseo-local-business' ) );
}
require AIOSEO_LOCAL_BUSINESS_DIR . $path;
}
$this->setDev();
}
/**
* Load the version of the plugin we are currently using.
*
* @since 1.2.4
*
* @return void
*/
private function setDev() {
if (
! class_exists( '\Dotenv\Dotenv' ) ||
! file_exists( AIOSEO_LOCAL_BUSINESS_DIR . '/build/.env' )
) {
return;
}
$dotenv = \Dotenv\Dotenv::createUnsafeImmutable( AIOSEO_LOCAL_BUSINESS_DIR, '/build/.env' );
$dotenv->load();
$domain = strtolower( getenv( 'VITE_AIOSEO_LOCAL_BUSINESS_DOMAIN' ) );
if ( ! empty( $domain ) ) {
$this->isDev = true;
}
}
/**
* Register styles.
*
* @since 1.1.0
*
* @return void
*/
public function registerStyles() {
aioseoLocalBusiness()->assets->registerCss( 'src/assets/scss/business-info.scss' );
aioseoLocalBusiness()->assets->registerCss( 'src/assets/scss/opening-hours.scss' );
}
/**
* Load our classes.
*
* @since 1.0.0
*
* @return void
*/
public function load() {
aioseo()->helpers->loadTextDomain( 'aioseo-local-business' );
$this->cache = new Utils\Cache();
$this->assets = new Utils\Assets();
$this->internalOptions = new Utils\InternalOptions();
$this->updates = new Main\Updates();
$this->admin = new Admin\Admin();
$this->usage = new Admin\Usage();
$this->postType = new Admin\Location();
$this->taxonomy = new Admin\LocationCategory();
$this->locations = new Locations\Locations();
$this->maps = new Locations\Maps();
$this->shortcodes = new Shortcodes\Shortcodes();
$this->blocks = new Blocks\Blocks();
$this->widgets = new Widgets\Widgets();
$this->tags = new Utils\Tags();
$this->helpers = new Utils\Helpers();
$this->search = new Main\Search();
$this->templates = new Utils\Templates();
$this->access = new Utils\Access();
$this->schema = new Schema\Schema();
$this->activate = new Main\Activate();
$this->api = new Api\Api();
$this->import = new Import\Import();
$this->kgOrganization = new Schema\Graphs\KgOrganization();
// Load into main aioseo instance.
aioseo()->addons->loadAddon( 'localBusiness', $this );
}
}
}
namespace {
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* The function which returns the one LocalBusiness instance.
*
* @since 1.0.0
*
* @return \AIOSEO\Plugin\Addon\LocalBusiness\LocalBusiness
*/
function aioseoLocalBusiness() {
return \AIOSEO\Plugin\Addon\LocalBusiness\LocalBusiness::instance();
}
if ( ! function_exists( 'aioseo_local_business_info' ) ) {
/**
* Global function for business info output.
*
* @param array $args
* @return void
*/
function aioseo_local_business_info( $args = [] ) {
$shortcodeArgs = [];
foreach ( $args as $key => $value ) {
$shortcodeArgs[ aioseo()->helpers->toSnakeCase( $key ) ] = $value;
}
echo aioseoLocalBusiness()->shortcodes->businessInfo( $shortcodeArgs ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
}
if ( ! function_exists( 'aioseo_local_opening_hours' ) ) {
/**
* Global function for opening hours output.
*
* @param array $args Opening hours arguments.
* @return void
*/
function aioseo_local_opening_hours( $args = [] ) {
$shortcodeArgs = [];
foreach ( $args as $key => $value ) {
$shortcodeArgs[ aioseo()->helpers->toSnakeCase( $key ) ] = $value;
}
echo aioseoLocalBusiness()->shortcodes->openingHours( $shortcodeArgs ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
}
if ( ! function_exists( 'aioseo_local_locations' ) ) {
/**
* Global function for locations output.
*
* @param array $args Locations arguments.
* @return void
*/
function aioseo_local_locations( $args = [] ) {
$shortcodeArgs = [];
foreach ( $args as $key => $value ) {
$shortcodeArgs[ aioseo()->helpers->toSnakeCase( $key ) ] = $value;
}
echo aioseoLocalBusiness()->shortcodes->locations( $shortcodeArgs ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
}
if ( ! function_exists( 'aioseo_local_map' ) ) {
/**
* Global function for locations output.
*
* @param array $args Locations arguments.
* @return void
*/
function aioseo_local_map( $args = [] ) {
$shortcodeArgs = [];
foreach ( $args as $key => $value ) {
$shortcodeArgs[ aioseo()->helpers->toSnakeCase( $key ) ] = $value;
}
echo aioseoLocalBusiness()->shortcodes->map( $shortcodeArgs ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
}
} app/Api/Maps.php 0000644 00000002710 15172727771 0007466 0 ustar 00 <?php
namespace AIOSEO\Plugin\Addon\LocalBusiness\Api;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Map class for the API.
*
* @since 1.1.3
*/
class Maps {
/**
* Check if an API key has access to a library.
*
* @since 1.1.3
*
* @param \WP_REST_Request $request The REST Request
* @return \WP_REST_Response The response.
*/
public static function checkApiAccess( $request ) {
$params = $request->get_json_params();
if ( empty( $params['apiKey'] ) || empty( $params['apiName'] ) ) {
return new \WP_REST_Response( [
'success' => false
], 400 );
}
$updateOption = false;
switch ( $params['apiName'] ) {
case 'places/embed':
$updateOption = 'mapsEmbedApiEnabled';
$url = add_query_arg( [
'key' => $params['apiKey'],
'q' => 'New+York'
], 'https://www.google.com/maps/embed/v1/place' );
break;
}
if ( empty( $url ) ) {
return new \WP_REST_Response( [
'success' => false
], 400 );
}
$checkApiAccess = wp_remote_get( $url );
if ( 200 === wp_remote_retrieve_response_code( $checkApiAccess ) ) {
if ( $updateOption ) {
aioseo()->options->localBusiness->maps->{$updateOption} = true;
}
return new \WP_REST_Response( [
'success' => true
], 200 );
}
if ( $updateOption ) {
aioseo()->options->localBusiness->maps->{$updateOption} = false;
}
return new \WP_REST_Response( [
'success' => false
], 400 );
}
} app/Api/Api.php 0000644 00000002206 15172727771 0007277 0 ustar 00 <?php
namespace AIOSEO\Plugin\Addon\LocalBusiness\Api;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Api class for the admin.
*
* @since 1.1.3
*/
class Api {
/**
* The routes we use in the rest API.
*
* @since 1.1.3
*
* @var array
*/
protected $routes = [
// phpcs:disable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound
// phpcs:disable Generic.Files.LineLength.MaxExceeded
'POST' => [
'local-business/maps/check-api-enabled' => [
'callback' => [ 'Maps', 'checkApiAccess', 'AIOSEO\\Plugin\\Addon\\LocalBusiness\\Api' ],
'access' => 'aioseo_local_seo_settings'
],
'local-business/import-plugins' => [
'callback' => [ 'Import', 'importPlugins', 'AIOSEO\\Plugin\\Addon\\LocalBusiness\\Api' ],
'access' => 'aioseo_local_seo_settings'
]
]
// phpcs:enable WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound
// phpcs:enable Generic.Files.LineLength.MaxExceeded
];
/**
* Get all the routes to register.
*
* @since 1.1.3
*
* @return array An array of routes.
*/
public function getRoutes() {
return $this->routes;
}
} app/Api/Import.php 0000644 00000001633 15172727771 0010043 0 ustar 00 <?php
namespace AIOSEO\Plugin\Addon\LocalBusiness\Api;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Import class for the API.
*
* @since 1.3.0
*/
class Import {
/**
* Import data from a plugin.
*
* @since 1.3.0
*
* @param \WP_REST_Request $request The REST Request
* @return \WP_REST_Response The response.
*/
public static function importPlugins( $request ) {
$plugins = $request->get_json_params();
if ( empty( $plugins ) || ! is_array( $plugins ) ) {
return new \WP_REST_Response( [
'success' => false
], 400 );
}
foreach ( $plugins as $plugin ) {
if ( empty( $plugin['plugin'] ) ) {
continue;
}
aioseoLocalBusiness()->import->startImport( $plugin['plugin'] );
}
return new \WP_REST_Response( [
'success' => true,
'localBusinessOptions' => aioseo()->options->localBusiness->all(),
], 200 );
}
} app/Locations/Maps.php 0000644 00000007026 15172727771 0010715 0 ustar 00 <?php
namespace AIOSEO\Plugin\Addon\LocalBusiness\Locations;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* The Maps class.
*
* @since 1.1.3
*/
class Maps {
/**
* Map load event.
*
* @since 1.1.3
*
* @var string
*/
public $mapLoadEvent = 'aioseo-local-map-load';
/**
* Class constructor.
*
* @since 1.1.3
*/
public function __construct() {
add_action( 'init', [ $this, 'init' ] );
add_action( 'admin_enqueue_scripts', [ $this, 'initAdmin' ] );
}
/**
* Init the class by registering our scripts.
*
* @since 1.1.3
*
* @return void
*/
public function init() {
// Here we just register scripts and styles which will be enqueued when the block is used.
$this->registerScripts();
$this->registerStyles();
}
/**
* Init the class by registering our scripts and enqueuing if we're on Gutenberg.
*
* @since 1.1.3
*
* @return void
*/
public function initAdmin() {
// Enqueuing from the block rendering does not work in the admin.
// So we enqueue our scripts here if we're in the block editor for a nice map preview.
$screen = aioseo()->helpers->getCurrentScreen();
if ( method_exists( $screen, 'is_block_editor' ) && $screen->is_block_editor() ) {
$this->enqueues();
}
}
/**
* Register scripts.
*
* @since 1.1.3
*
* @return void
*/
public function registerScripts() {
aioseoLocalBusiness()->assets->registerJs( 'src/js-api-loader.js', [], null, [] );
aioseoLocalBusiness()->assets->registerJs( 'src/map.js', [], [
'apiKey' => aioseo()->options->localBusiness->maps->apiKey,
'mapLoadEvent' => $this->mapLoadEvent
], 'aioseoMapOptions' );
}
/**
* Registers styles.
*
* @since 1.1.3
*
* @return void
*/
public function registerStyles() {
aioseoLocalBusiness()->assets->registerCss( 'src/assets/scss/location-map.scss' );
}
/**
* Enqueues needed scripts and styles.
*
* @since 1.1.3
*
* @return void
*/
public function enqueues() {
aioseoLocalBusiness()->assets->enqueueCss( 'src/assets/scss/location-map.scss' );
aioseoLocalBusiness()->assets->enqueueJs( 'src/js-api-loader.js' );
aioseoLocalBusiness()->assets->enqueueJs( 'src/map.js' );
}
/**
* Adds inline script to start a map.
*
* @since 1.1.3
*
* @param string $data Data to be encoded.
* @return void
*/
public function mapStartEvent( $data ) {
$data = wp_json_encode( $data );
wp_add_inline_script( aioseoLocalBusiness()->assets->jsHandle( 'src/map.js' ), "
document.dispatchEvent(new CustomEvent('{$this->mapLoadEvent}', {
detail : $data
}))
"
);
}
/**
* Adds map information in the Rest API for a Location.
*
* @since 1.1.3
*
* @param object $object The rest object.
* @return object|null Map information.
*/
public function restMapInfo( $object ) {
$location = aioseoLocalBusiness()->locations->getLocation( $object['id'] );
if ( empty( $location->maps ) ) {
return null;
}
$location->maps->infoWindowContent = $this->getMarkerInfoWindow( $location );
return $location->maps;
}
/**
* Returns the template for the marker's info window.
*
* @since 1.1.3
*
* @param object $locationData The location data.
* @return string Marker's info window template.
*/
public function getMarkerInfoWindow( $locationData ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
$template = aioseoLocalBusiness()->templates->locateTemplate( 'MapMarkerInfoWindow.php' );
ob_start();
require $template;
return ob_get_clean();
}
} app/Locations/Locations.php 0000644 00000031647 15172727771 0011756 0 ustar 00 <?php
namespace AIOSEO\Plugin\Addon\LocalBusiness\Locations;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
use AIOSEO\Plugin\Common\Models;
/**
* The Locations class.
*
* @since 1.1.0
*/
class Locations {
/**
* Returns all locations.
*
* @since 1.1.0
*
* @param array $args Query args to be passed down to WP_Query.
* @return array An array of WP_Post.
*/
public function getLocations( $args = [] ) {
$args = wp_parse_args( $args, [
'post_type' => aioseoLocalBusiness()->postType->getName(),
'no_found_rows' => true,
'update_post_meta_cache' => false,
'update_post_term_cache' => false,
'posts_per_page' => 100,
'post_status' => 'publish'
] );
$args = apply_filters( 'aioseo_local_business_get_locations_args', $args );
$posts = new \WP_Query( $args );
return apply_filters( 'aioseo_local_business_get_locations_posts', $posts->posts, $args );
}
/**
* Returns the JSON data for the given location.
*
* @since 1.1.0
*
* @param integer $postId The post id.
* @return false|object The decoded JSON data.
*/
public function getLocation( $postId ) {
if ( ! get_post( $postId ) ) {
return false;
}
$post = Models\Post::getPost( $postId );
return apply_filters( 'aioseo_local_business_get_location', $post->local_seo, $postId );
}
/**
* Returns the locations categories.
*
* @since 1.1.0
*
* @return array List of category objects.
*/
public function getLocationCategories() {
$args = apply_filters( 'aioseo_local_business_get_location_category_args', [
'taxonomy' => aioseoLocalBusiness()->taxonomy->getName(),
'orderby' => 'name'
] );
return apply_filters( 'aioseo_local_business_get_location_categories', get_categories( $args ), $args );
}
/**
* Returns locations by category.
*
* @since 1.1.0
*
* @param integer $termId The term id.
* @param array $args Query args to be passed down to WP_Query.
* @return array An array of WP_Post.
*/
public function getLocationsByCategory( $termId, $args = [] ) {
$args = wp_parse_args( $args, [
'post_type' => aioseoLocalBusiness()->postType->getName(),
'post_status' => 'publish',
'posts_per_page' => 100,
'tax_query' => [ // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query
[
'taxonomy' => aioseoLocalBusiness()->taxonomy->getName(),
'field' => 'term_id',
'terms' => $termId
],
]
] );
$args = apply_filters( 'aioseo_local_business_get_locations_by_category_args', $args, $termId );
$posts = new \WP_Query( $args );
return apply_filters( 'aioseo_local_business_get_locations_by_category_posts', $posts->posts, $args, $termId );
}
/**
* Outputs the business info.
*
* @since 1.1.0
*
* @param integer|string $postId The location ID or 'global' keyword.
* @param array $instance An array of attributes used by the view.
* @return void
*/
public function outputBusinessInfo( $postId, $instance = [] ) {
$postId = $this->maybeGlobalLocationId( $postId );
if ( ! $this->canLocationIdRender( $postId ) ) {
return;
}
$locationData = $this->getLocation( $postId );
if ( 'global' === $postId ) {
$locationData = aioseoLocalBusiness()->helpers->getLocalBusinessOptions();
}
$locationData = ! empty( $locationData->locations->business ) ? $locationData->locations->business : null;
$locationData = ! empty( $instance['dataObject'] ) ? json_decode( $instance['dataObject'] ) : $locationData;
if ( empty( $locationData ) ) {
return;
}
// Parse defaults.
$instance = wp_parse_args( $instance, [
'class' => '',
'showLabels' => true,
'showIcons' => true,
'showAddress' => true,
'showName' => true,
'showVat' => true,
'showTax' => true,
'showChamberId' => true,
'showPhone' => true,
'showFax' => true,
'showCountryCode' => true,
'showEmail' => true,
'addressFormat' => '#streetLine1, #streetLine2 #newLine #zipCode - #city - #state #newLine #country',
'addressLabel' => __( 'Address:', 'aioseo-local-business' ),
'emailLabel' => __( 'Email:', 'aioseo-local-business' ),
'phoneLabel' => __( 'Phone:', 'aioseo-local-business' ),
'faxLabel' => __( 'Fax:', 'aioseo-local-business' ),
'vatIdLabel' => __( 'VAT ID:', 'aioseo-local-business' ),
'taxIdLabel' => __( 'Tax ID:', 'aioseo-local-business' )
] );
$instance['class'] .= $instance['showLabels'] ? '' : ' hide-label ';
$instance['class'] .= $instance['showIcons'] ? '' : ' hide-icon ';
$instance = apply_filters( 'aioseo_local_business_output_business_info_instance', $instance, $postId, $locationData );
$locationData = apply_filters( 'aioseo_local_business_output_business_info_location_data', $locationData, $instance, $postId );
aioseoLocalBusiness()->assets->enqueueCss( 'src/assets/scss/business-info.scss' );
$template = aioseoLocalBusiness()->templates->locateTemplate( 'BusinessInfo.php' );
require $template;
}
/**
* Outputs a list of locations by category.
*
* @since 1.1.0
*
* @param integer $termId The term ID.
* @param array $instance An array of attributes used by the view.
* @return void
*/
public function outputLocationCategory( $termId, $instance = [] ) {
if ( ! $this->canLocationIdRender( $termId ) ) {
return;
}
$locations = $this->getLocationsByCategory( $termId );
if ( empty( $locations ) ) {
return sprintf(
// Translators: 1 - The post type plural label.
__( 'No %1$s found', 'aioseo-local-business' ),
aioseoLocalBusiness()->postType->getPluralLabel()
);
}
$instance = wp_parse_args( $instance, [
'class' => '',
] );
$instance = apply_filters( 'aioseo_local_business_output_location_category_instance', $instance, $termId, $locations );
$locations = apply_filters( 'aioseo_local_business_output_location_category_location_data', $locations, $instance, $termId );
$template = aioseoLocalBusiness()->templates->locateTemplate( 'Locations.php' );
require $template;
}
/**
* Outputs the opening hours.
*
* @since 1.1.0
*
* @param integer|string $postId The location ID or 'global' keyword.
* @param array $instance An array of attributes used by the view.
* @return void
*/
public function outputOpeningHours( $postId, $instance = [] ) {
$postId = $this->maybeGlobalLocationId( $postId );
if ( ! $this->canLocationIdRender( $postId ) ) {
return;
}
$locationData = $this->getLocation( $postId );
$openingHoursData = ! empty( $instance['dataObject'] ) ?
json_decode( $instance['dataObject'] ) :
( ! empty( $locationData->openingHours ) ? $locationData->openingHours : null );
if ( 'global' === $postId || ! empty( $openingHoursData->useDefaults ) ) {
$locationData = aioseoLocalBusiness()->helpers->getLocalBusinessOptions();
$openingHoursData = $locationData->openingHours;
}
if ( empty( $openingHoursData->show ) ) {
if ( aioseo()->blocks->isGBEditor() ) {
return __( 'Your Opening Hours settings are disabled. Please enable them to use the Opening Hours block.', 'aioseo-local-business' );
}
return;
}
// Parse defaults.
$instance = wp_parse_args( $instance, [ // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
'class' => '',
'showTitle' => true,
'showIcons' => true,
'showMonday' => true,
'showTuesday' => true,
'showWednesday' => true,
'showThursday' => true,
'showFriday' => true,
'showSaturday' => true,
'showSunday' => true
] );
$instance = apply_filters( 'aioseo_local_business_output_opening_hours_instance', $instance, $postId, $openingHoursData );
$openingHoursData = apply_filters( 'aioseo_local_business_output_opening_hours_data', $openingHoursData, $instance, $postId );
aioseoLocalBusiness()->assets->enqueueCss( 'src/assets/scss/opening-hours.scss' );
$template = aioseoLocalBusiness()->templates->locateTemplate( 'OpeningHours.php' );
require $template;
}
/**
* Outputs a list of categories.
*
* @since 1.1.1
*
* @param array $instance An array of attributes used by the view.
* @return void
*/
public function outputLocationCategories( $instance = [] ) {
$categories = $this->getLocationCategories();
if ( empty( $categories ) ) {
return sprintf(
// Translators: 1 - The post type plural label.
__( 'No %1$s found', 'aioseo-local-business' ),
aioseoLocalBusiness()->taxonomy->getPluralLabel()
);
}
$instance = wp_parse_args( $instance, [
'class' => '',
] );
$instance = apply_filters( 'aioseo_local_business_output_location_categories_instance', $instance );
$categories = apply_filters( 'aioseo_local_business_output_location_categories', $categories, $instance );
$template = aioseoLocalBusiness()->templates->locateTemplate( 'LocationCategories.php' );
require $template;
}
/**
* Outputs a map.
*
* @since 1.1.3
*
* @param array $instance An array of attributes used by the view.
* @return void
*/
public function outputLocationMap( $postId, $instance = [] ) {
$postId = $this->maybeGlobalLocationId( $postId );
if ( ! $this->canLocationIdRender( $postId ) ) {
return;
}
$locationData = $this->getLocation( $postId );
if ( 'global' === $postId ) {
$locationData = aioseoLocalBusiness()->helpers->getLocalBusinessOptions();
}
$locationMapData = ! empty( $locationData->maps ) ? $locationData->maps : null;
$locationMapData = ! empty( $instance['dataObject'] ) ? json_decode( $instance['dataObject'] ) : $locationMapData;
if ( empty( $locationMapData ) ) {
return;
}
// Parse defaults.
$instance = wp_parse_args( $instance, [
'class' => '',
'showLabels' => true,
'showIcons' => true,
'width' => '100%',
'height' => '450px'
] );
$instance['class'] .= $instance['showLabels'] ? '' : ' hide-label ';
$instance['class'] .= $instance['showIcons'] ? '' : ' hide-icon ';
$instance = apply_filters( 'aioseo_local_business_output_location_map_instance', $instance, $postId, $locationData );
$locationMapData = apply_filters( 'aioseo_local_business_output_location_map_data', $locationMapData, $instance, $postId );
$instance['mapId'] = uniqid( 'aioseo-local-map-' );
$customMarker = ! empty( $instance['customMarker'] ) ? $instance['customMarker'] : $locationMapData->customMarker;
aioseoLocalBusiness()->maps->enqueues();
// Frontend only.
if ( ! is_admin() ) {
aioseoLocalBusiness()->maps->mapStartEvent( [
'element' => '#' . $instance['mapId'],
'mapOptions' => $locationMapData->mapOptions,
'customMarker' => ! empty( $customMarker ) ? $customMarker : aioseo()->options->localBusiness->maps->customMarker,
'placeId' => aioseo()->options->localBusiness->maps->mapsEmbedApiEnabled ? $locationMapData->placeId : null,
'instance' => $instance,
'infoWindowContent' => aioseoLocalBusiness()->maps->getMarkerInfoWindow( $locationData )
] );
}
$template = aioseoLocalBusiness()->templates->locateTemplate( 'Map.php' );
require $template;
}
/**
* Determine if we should be loading our global information.
*
* @since 1.1.0
*
* @param void|string|integer $locationId The post ID.
* @return mixed|string The post ID or 'global'.
*/
private function maybeGlobalLocationId( $locationId ) {
if ( empty( $locationId ) && ! aioseo()->options->localBusiness->locations->general->multiple ) {
$locationId = 'global';
}
return $locationId;
}
/**
* Returns if a given location ID is allowed to render.
*
* @since 1.1.0
*
* @param string|integer|null $locationId The postId.
* @return bool Should the location be rendered.
*/
private function canLocationIdRender( $locationId = null ) {
if (
( aioseo()->options->localBusiness->locations->general->multiple && 'global' === $locationId ) ||
! aioseo()->options->localBusiness->locations->general->multiple && 'global' !== $locationId
) {
return false;
}
return true;
}
/**
* Formats a phone number with the country code.
*
* @since 1.1.0
*
* @param string $phoneNumber The phone number.
* @param bool $keepCountryCode Keep the country code.
* @return string Formatted phone number.
*/
public function formatPhone( $phoneNumber, $keepCountryCode = true ) {
return $keepCountryCode ? $phoneNumber : preg_replace( '/^\+[0-9]+\s/', '', $phoneNumber );
}
/**
* Finds a location based on the name.
*
* @since 1.3.0
*
* @param string $locationName The location name.
* @return array The location found.
*/
public function getLocationByName( $locationName, $status = 'any' ) {
$foundLocations = $this->getLocations( [
'name' => sanitize_title( $locationName ),
'post_status' => $status
] );
return is_array( $foundLocations ) ? current( $foundLocations ) : [];
}
} app/Shortcodes/Shortcodes.php 0000644 00000011510 15172727771 0012305 0 ustar 00 <?php
namespace AIOSEO\Plugin\Addon\LocalBusiness\Shortcodes;
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* The Shortcodes class.
*
* @since 1.1.0
*/
class Shortcodes {
/**
* The shortcodes.
*
* @since 1.1.0
*
* @var string Array of shortcodes and callbacks.
*/
protected $shortcodes = [
'aioseo_local_business_info' => 'businessInfo',
'aioseo_local_locations' => 'locations',
'aioseo_local_opening_hours' => 'openingHours',
'aioseo_local_map' => 'map'
];
/**
* Class constructor.
*
* @since 1.1.0
*/
public function __construct() {
foreach ( $this->shortcodes as $shortcode => $callback ) {
add_shortcode( $shortcode, [ $this, $callback ] );
}
}
/**
* Business info shortcode. Displays a location's business information.
*
* @since 1.1.0
*
* @param array $attributes The shortcode attributes.
* @return string The rendered shortcode.
*/
public function businessInfo( $attributes = [] ) {
$defaults = [
'location_id' => '',
'show_labels' => true,
'show_icons' => true,
'show_name' => true,
'show_address' => true,
'show_phone' => true,
'show_fax' => true,
'show_country_code' => true,
'show_email' => true,
'show_vat' => true,
'show_tax' => true,
'show_chamber_id' => true,
'address_label' => __( 'Address:', 'aioseo-local-business' ),
'vat_id_label' => __( 'VAT ID:', 'aioseo-local-business' ),
'tax_id_label' => __( 'Tax ID:', 'aioseo-local-business' ),
'phone_label' => __( 'Phone:', 'aioseo-local-business' ),
'fax_label' => __( 'Fax:', 'aioseo-local-business' ),
'email_label' => __( 'Email:', 'aioseo-local-business' )
];
$attributes = $this->convertSnakeCaseAttributes( $attributes, $defaults );
ob_start();
aioseoLocalBusiness()->locations->outputBusinessInfo( absint( $attributes['locationId'] ), $attributes );
return ob_get_clean();
}
/**
* Locations shortcode. Displays a list of locations based on a location category.
*
* @since 1.1.0
*
* @param array $attr The shortcode attributes.
* @return string The rendered shortcode.
*/
public function locations( $attr = [] ) {
$attr = shortcode_atts( [ 'category_id' => '' ], $attr, 'aioseo_locations' );
$attributes = [ 'categoryId' => $attr['category_id'] ];
ob_start();
aioseoLocalBusiness()->locations->outputLocationCategory( absint( $attributes['categoryId'] ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
return ob_get_clean();
}
/**
* Opening hours shortcode. Displays a location's opening hours.
*
* @since 1.1.0
*
* @param array $attributes The shortcode attributes.
* @return string The rendered shortcode.
*/
public function openingHours( $attributes = [] ) {
$defaults = [
'location_id' => '',
'show_title' => true,
'show_icons' => true,
'show_monday' => true,
'show_tuesday' => true,
'show_wednesday' => true,
'show_thursday' => true,
'show_friday' => true,
'show_saturday' => true,
'show_sunday' => true,
'label' => __( 'Our Opening Hours:', 'aioseo-local-business' )
];
$attributes = $this->convertSnakeCaseAttributes( $attributes, $defaults );
ob_start();
aioseoLocalBusiness()->locations->outputOpeningHours( absint( $attributes['locationId'] ), $attributes ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
return ob_get_clean();
}
/**
* Map shortcode. Displays a location's map.
*
* @since 1.1.3
*
* @param array $attributes The shortcode attributes.
* @return string The rendered shortcode.
*/
public function map( $attributes = [] ) {
$defaults = [
'location_id' => '',
'show_label' => true,
'show_icon' => true,
'width' => '100%',
'height' => '450px',
'label' => __( 'Our location:', 'aioseo-local-business' )
];
$attributes = $this->convertSnakeCaseAttributes( $attributes, $defaults );
ob_start();
aioseoLocalBusiness()->locations->outputLocationMap( absint( $attributes['locationId'] ), $attributes );
return ob_get_clean();
}
/**
* Convert snake case attributes to camel case.
*
* @since 4.1.5
*
* @param array $attributes The attributes.
* @param array $defaults The defaults.
* @return array Converted attributes.
*/
private function convertSnakeCaseAttributes( $attributes, $defaults = [] ) {
$attributes = wp_parse_args( $attributes, $defaults );
$convertedAttributes = [];
foreach ( $attributes as $key => $value ) {
$convertedAttributes[ aioseo()->helpers->toCamelCase( $key ) ] = is_bool( $defaults[ $key ] )
? filter_var( $value, FILTER_VALIDATE_BOOLEAN )
: $value;
}
return $convertedAttributes;
}
} app/Views/LocationCategories.php 0000644 00000001074 15172727771 0012732 0 ustar 00 <?php
/**
* This is the output for Local Business - Locations by Category on the frontend.
*
* @since 1.1.1
* @version 1.1.1
*/
// phpcs:disable VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable
// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
?>
<ul class="aioseo-location-categories <?php echo esc_attr( $instance['class'] ); ?>">
<?php foreach ( $categories as $category ) { ?>
<li>
<a href="<?php echo esc_attr( get_term_link( $category ) ); ?>"><?php echo esc_html( $category->name ); ?></a>
</li>
<?php } ?>
</ul>