Plugin language).
* Names are shown in their own language, so they are not translated.
*/
public const array LANGUAGES = array(
'en_US' => 'English',
'es_ES' => 'Español',
'de_DE' => 'Deutsch',
'fr_FR' => 'Français',
'pt_BR' => 'Português (Brasil)',
'ru_RU' => 'Русский',
'tr_TR' => 'Türkçe',
'hy' => 'Հայերեն',
'ja' => '日本語',
'zh_CN' => '简体中文',
);
/**
* @var Plugin|null
*/
private static $instance = null;
/**
* @var Settings
*/
public $settings;
/**
* @var Admin
*/
public $admin;
/**
* @var REST
*/
public $rest;
/**
* Singleton.
*
* @return Plugin
*/
public static function instance() {
if ( null === self::$instance ) {
self::$instance = new self();
self::$instance->init();
}
return self::$instance;
}
/**
* Init hooks.
*/
public function init() {
$this->settings = new Settings();
$this->admin = new Admin( $this->settings );
$this->rest = new REST( $this->settings );
add_action( 'init', array( $this, 'maybe_upgrade' ), 1 );
add_action( 'admin_init', array( $this, 'verify_author_contacts' ) );
add_action( 'admin_notices', array( $this, 'author_tamper_notice' ) );
Jobs::register();
Rules::register();
add_action( 'template_redirect', array( $this, 'maybe_redirect_old_slug' ), 1 );
add_action( 'init', array( $this, 'load_textdomain' ) );
add_filter( 'plugin_locale', array( $this, 'plugin_language' ), 10, 2 );
add_filter( 'load_textdomain_mofile', array( $this, 'plugin_language_mofile' ), 10, 2 );
add_filter( 'load_script_translation_file', array( $this, 'plugin_language_json' ), 10, 3 );
add_action( 'before_woocommerce_init', array( $this, 'declare_woo_compatibility' ) );
}
/**
* Declare compatibility with modern WooCommerce features (HPOS, blocks).
* Without this, WooCommerce shows compatibility warnings since 8.0.
*/
public function declare_woo_compatibility() {
if ( ! class_exists( '\Automattic\WooCommerce\Utilities\FeaturesUtil', false ) ) {
return;
}
\Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'custom_order_tables', RAFGRID_FILE, true );
\Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'cart_checkout_blocks', RAFGRID_FILE, true );
}
/**
* Verify that the official author contacts were not silently replaced.
*
* @return bool
*/
public function verify_author_contacts(): bool {
return hash_equals( self::AUTHOR_SIGNATURE, Author::signature() );
}
/**
* Admin notice when the author contacts do not match the signature.
*/
public function author_tamper_notice() {
if ( ! current_user_can( 'manage_options' ) || $this->verify_author_contacts() ) {
return;
}
if ( ! self::is_plugin_screen() ) {
return;
}
echo '
';
echo esc_html__( 'Rafgrid: the official author support contacts in this copy were modified. Official support: ', 'rafgrid' );
echo esc_html( Author::line() );
echo '
';
}
/**
* Versioned upgrade routine: runs on version change without reactivation,
* so DB tables and defaults appear after a normal plugin update too.
*/
public function maybe_upgrade() {
if ( get_option( 'rafgrid_version' ) === RAFGRID_VERSION ) {
return;
}
Migrate::run();
Settings::ensure_defaults();
History::create_table();
Audit::create_table();
Jobs::ensure_scheduled();
update_option( 'rafgrid_version', RAFGRID_VERSION );
}
/**
* Plugin language override (Settings -> Plugin language). Does not change the whole admin.
*
* @param string $locale Locale.
* @param string $domain Text domain.
* @return string
*/
public function plugin_language( $locale, $domain ) {
if ( 'rafgrid' !== $domain ) {
return $locale;
}
$lang = $this->language_override();
return '' !== $lang ? $lang : $locale;
}
/**
* Locale chosen in Settings -> Plugin language, or '' to follow the site.
*
* @return string
*/
private function language_override(): string {
$lang = (string) $this->settings->get( 'language', 'auto' );
return array_key_exists( $lang, self::LANGUAGES ) ? $lang : '';
}
/**
* Plugin language for PHP strings: point just-in-time loading of this text
* domain at the chosen locale (en_US has no file, so strings stay English).
*
* @param string $mofile Translation file.
* @param string $domain Text domain.
* @return string
*/
public function plugin_language_mofile( $mofile, $domain ) {
$lang = 'rafgrid' === $domain ? $this->language_override() : '';
return '' !== $lang ? RAFGRID_DIR . 'languages/rafgrid-' . $lang . '.mo' : $mofile;
}
/**
* Plugin language for the React app's JSON translations.
*
* @param string|false $file Translation file.
* @param string $handle Script handle.
* @param string $domain Text domain.
* @return string|false
*/
public function plugin_language_json( $file, $handle, $domain ) {
$lang = 'rafgrid' === $domain ? $this->language_override() : '';
if ( '' === $lang || 'rafgrid-app' !== $handle ) {
return $file;
}
return RAFGRID_DIR . 'languages/rafgrid-' . $lang . '-' . md5( 'build/index.js' ) . '.json';
}
/**
* 301 redirect from a renamed slug (map written when Slug is edited in the sheet).
*/
public function maybe_redirect_old_slug() {
if ( ! is_404() ) {
return;
}
$map = get_option( 'rafgrid_redirects', array() );
if ( ! is_array( $map ) || empty( $map ) ) {
return;
}
$path = trim( (string) wp_parse_url( esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ?? '' ) ), PHP_URL_PATH ), '/' );
if ( isset( $map[ $path ] ) ) {
wp_safe_redirect( home_url( '/' . $map[ $path ] . '/' ), 301 );
exit;
}
}
/**
* Register the bundled /languages folder for just-in-time loading; language
* packs from translate.wordpress.org take precedence. The filters above
* apply the "Plugin language" setting to this text domain only.
*/
public function load_textdomain() {
load_plugin_textdomain( 'rafgrid', false, dirname( plugin_basename( RAFGRID_FILE ) ) . '/languages' ); // phpcs:ignore PluginCheck.CodeAnalysis.DiscouragedFunctions.load_plugin_textdomainFound -- Needed for the per-plugin language setting and the bundled hy/ru_RU files.
}
/**
* Activation: defaults + history table.
*/
public static function activate() {
Migrate::run();
Settings::ensure_defaults();
History::create_table();
Audit::create_table();
Jobs::ensure_scheduled();
}
/**
* Is the current admin screen one of this plugin's pages (sheet, docs, settings)?
*
* @return bool
*/
public static function is_plugin_screen(): bool {
$screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null;
return $screen && str_contains( (string) $screen->id, 'rafgrid' );
}
/**
* Is WooCommerce active?
*
* @return bool
*/
public static function has_woo() {
return class_exists( 'WooCommerce', false ) || function_exists( 'wc_get_product' ) || post_type_exists( 'product' );
}
}