3task Glossary: '; echo esc_html__( 'Please deactivate the old "Simple SEO Glossary" plugin. Both plugins cannot run simultaneously.', '3task-glossary' ); echo '

'; } ); return; } // Plugin constants (with defined checks for safety). if ( ! defined( 'AZGL_VERSION' ) ) { define( 'AZGL_VERSION', '2.4.0' ); } if ( ! defined( 'AZGL_PLUGIN_FILE' ) ) { define( 'AZGL_PLUGIN_FILE', __FILE__ ); } if ( ! defined( 'AZGL_PLUGIN_DIR' ) ) { define( 'AZGL_PLUGIN_DIR', plugin_dir_path( __FILE__ ) ); } require_once AZGL_PLUGIN_DIR . 'includes/class-content.php'; require_once AZGL_PLUGIN_DIR . 'includes/class-kb.php'; if ( ! defined( 'AZGL_PLUGIN_URL' ) ) { define( 'AZGL_PLUGIN_URL', plugin_dir_url( __FILE__ ) ); } if ( ! defined( 'AZGL_PLUGIN_BASENAME' ) ) { define( 'AZGL_PLUGIN_BASENAME', plugin_basename( __FILE__ ) ); } // Limits for Lite version (no functional limits for WordPress.org compliance). if ( ! defined( 'AZGL_MAX_GLOSSARIES' ) ) { define( 'AZGL_MAX_GLOSSARIES', 999 ); } if ( ! defined( 'AZGL_MAX_ENTRIES' ) ) { define( 'AZGL_MAX_ENTRIES', 999999 ); } if ( ! defined( 'AZGL_SUPPORTER_MAX_GLOSSARIES' ) ) { define( 'AZGL_SUPPORTER_MAX_GLOSSARIES', 999 ); } if ( ! defined( 'AZGL_SUPPORTER_MAX_ENTRIES' ) ) { define( 'AZGL_SUPPORTER_MAX_ENTRIES', 999999 ); } /** * Main Plugin Class * * @since 2.0.0 */ final class AZ_Glossary_Lite { /** * Plugin instance. * * @var AZ_Glossary_Lite */ private static $instance = null; /** * Options handler. * * @var AZ_Glossary_Options */ public $options; /** * Admin handler. * * @var AZ_Glossary_Admin */ public $admin; /** * Frontend handler. * * @var AZ_Glossary_Frontend */ public $frontend; /** * Linker handler. * * @var AZ_Glossary_Linker */ public $linker; /** * Get plugin instance (Singleton). * * @return AZ_Glossary_Lite */ public static function get_instance() { if ( null === self::$instance ) { self::$instance = new self(); } return self::$instance; } /** * Constructor - private for Singleton. */ private function __construct() { $this->init(); } /** * Initialize plugin. */ private function init() { // Load classes. $this->load_classes(); // Load text domain early. add_action( 'init', array( $this, 'load_textdomain' ), 1 ); // Initialize components after plugins loaded. add_action( 'plugins_loaded', array( $this, 'init_components' ) ); // Activation/deactivation hooks. register_activation_hook( AZGL_PLUGIN_FILE, array( $this, 'activate' ) ); register_deactivation_hook( AZGL_PLUGIN_FILE, array( $this, 'deactivate' ) ); } /** * Load plugin text domain for translations. */ public function load_textdomain() { $options = get_option( 'azgl_options', array() ); $language = isset( $options['plugin_language'] ) ? $options['plugin_language'] : 'auto'; // If English is explicitly selected, don't load any translation (use source strings). if ( 'en_US' === $language ) { // Unload any existing translations. unload_textdomain( '3task-glossary' ); return; } // If specific non-English language is set, load that language file if it exists locally. // Otherwise WordPress.org handles translations automatically since 4.6+. if ( 'auto' !== $language && ! empty( $language ) ) { $mofile = AZGL_PLUGIN_DIR . 'languages/simple-seo-glossary-' . $language . '.mo'; if ( file_exists( $mofile ) ) { load_textdomain( '3task-glossary', $mofile ); } } } /** * Load required classes. */ private function load_classes() { $classes = array( 'includes/class-options.php', 'includes/class-admin.php', 'includes/class-frontend.php', 'includes/class-linker.php', 'includes/class-widget.php', ); foreach ( $classes as $class ) { $file = AZGL_PLUGIN_DIR . $class; if ( file_exists( $file ) ) { require_once $file; } } } /** * Initialize components. */ public function init_components() { // Pro replaces Free completely: never run both frontends (double schema and navigation). if ( defined( 'AZGL_PRO_VERSION' ) || class_exists( 'AZ_Glossary_Pro', false ) ) { return; } // Initialize options first. $this->options = new AZ_Glossary_Options(); // Initialize admin. if ( is_admin() ) { $this->admin = new AZ_Glossary_Admin( $this->options ); } // Initialize frontend. $this->frontend = new AZ_Glossary_Frontend( $this->options ); // Initialize linker. $this->linker = new AZ_Glossary_Linker( $this->options ); } /** * Notice shown while 3task Glossary Pro is active at the same time. */ public static function pro_active_notice() { if ( ! current_user_can( 'activate_plugins' ) ) { return; } echo '

'; esc_html_e( '3task Glossary Pro is active, so the free 3task Glossary plugin is paused. You can safely deactivate and delete the free plugin; your glossaries and settings are kept.', '3task-glossary' ); echo '

'; } /** * Plugin activation. */ public function activate() { // Check PHP version. if ( version_compare( PHP_VERSION, '7.4', '<' ) ) { deactivate_plugins( AZGL_PLUGIN_BASENAME ); wp_die( esc_html__( '3task Glossary requires PHP 7.4 or higher.', '3task-glossary' ), 'Plugin Activation Error', array( 'back_link' => true ) ); } // Check WordPress version. if ( version_compare( get_bloginfo( 'version' ), '5.8', '<' ) ) { deactivate_plugins( AZGL_PLUGIN_BASENAME ); wp_die( esc_html__( '3task Glossary requires WordPress 5.8 or higher.', '3task-glossary' ), 'Plugin Activation Error', array( 'back_link' => true ) ); } // Set default options if not exists. if ( false === get_option( 'azgl_options' ) ) { $defaults = array( 'glossaries' => array(), 'linking_mode' => 'selective', 'link_first_only' => true, 'link_class' => 'glossary-term', 'cache_enabled' => true, 'nav_style' => 'buttons', 'inactive_letters' => true, 'color_scheme' => 'emerald', 'dark_mode' => 'auto', 'show_credit_link' => false, 'credit_link_url' => 'https://www.3task.de', ); add_option( 'azgl_options', $defaults ); } // Store version. update_option( 'azgl_version', AZGL_VERSION ); // Flush rewrite rules. flush_rewrite_rules(); } /** * Plugin deactivation. */ public function deactivate() { // Clear transients. $this->clear_all_transients(); // Flush rewrite rules. flush_rewrite_rules(); } /** * Clear all plugin transients. */ private function clear_all_transients() { global $wpdb; // Delete all transients with our prefix. // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s", '%_transient_azgl_%' ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s", '%_transient_timeout_azgl_%' ) ); } /** * Check if Pro version is active. * * @return bool */ public function is_pro() { return false; } /** * Check if Supporter mode is active. * * @return bool */ public function is_supporter() { $options = get_option( 'azgl_options', array() ); return ! empty( $options['show_credit_link'] ); } /** * Get maximum allowed glossaries. * * @return int */ public function get_max_glossaries() { return $this->is_supporter() ? AZGL_SUPPORTER_MAX_GLOSSARIES : AZGL_MAX_GLOSSARIES; } /** * Get maximum allowed entries per glossary. * * @return int */ public function get_max_entries() { return $this->is_supporter() ? AZGL_SUPPORTER_MAX_ENTRIES : AZGL_MAX_ENTRIES; } /** * Get upgrade URL. * * @return string */ public function get_upgrade_url() { return 'https://www.3task.de/3task-glossary-pro/'; } /** * Get options handler (same API as Pro; the widget relies on it). * * @return AZ_Glossary_Options */ public function get_options() { return $this->options; } /** * Get all entries for a specific glossary. * * @param int $glossary_id Glossary page ID. * @return array Array of WP_Post objects. */ public function get_glossary_entries( $glossary_id ) { if ( ! AZGL_Content::public_page( $glossary_id ) ) { return array(); } $enabled = $this->options->get( 'cache_enabled', true ); $cache_key = 'azgl_entries_' . absint( $glossary_id ); $entries = $enabled ? get_transient( $cache_key ) : false; if ( false === $entries ) { $entries = get_posts( array( 'post_type' => 'page', 'post_status' => 'publish', 'has_password' => false, 'post_parent' => absint( $glossary_id ), 'posts_per_page' => -1, 'orderby' => 'title', 'order' => 'ASC' ) ); if ( $enabled ) { set_transient( $cache_key, $entries, HOUR_IN_SECONDS ); } } return array_values( array_filter( $entries ?: array(), array( 'AZGL_Content', 'public_page' ) ) ); } /** * Get entry count for a glossary. * * @param int $glossary_id The glossary parent page ID. * @return int Number of entries. */ public function get_entry_count( $glossary_id ) { $entries = $this->get_glossary_entries( $glossary_id ); return count( $entries ); } /** * Clear cache for a specific glossary. * * @param int $glossary_id The glossary parent page ID. */ public function clear_glossary_cache( $glossary_id ) { delete_transient( 'azgl_entries_' . $glossary_id ); delete_transient( 'azgl_az_nav_' . $glossary_id ); } } /** * Get plugin instance. * * @return AZ_Glossary_Lite */ if ( ! function_exists( 'azgl' ) ) { function azgl() { return AZ_Glossary_Lite::get_instance(); } } // Pro active at the same time: tell the admin, independent of plugin load order. add_action( 'plugins_loaded', static function () { if ( defined( 'AZGL_PRO_VERSION' ) && is_admin() ) { add_action( 'admin_notices', array( 'AZ_Glossary_Lite', 'pro_active_notice' ) ); } }, 5 ); // Initialize plugin. azgl();