1, 'website_name' => get_bloginfo('name'), 'banner_text' => 'Add as a preferred source on Google', 'banner_position' => 'bottom', 'banner_bg_color' => '#1a1a1a', 'text_color' => '#ffffff', 'badge_language' => 'auto', 'show_on_mobile' => 1, 'show_on_desktop' => 1, 'banner_trigger' => 'immediate', 'banner_scroll_percent' => 50, 'banner_delay_seconds' => 5, // New installs show the banner on every page view. Updating installs // have no 'banner_frequency' saved, and every consumer falls back to // 'remember' (hide for 7 days), so their behaviour is unchanged. 'banner_frequency' => 'always', 'banner_dismiss_days' => 7, 'display_on' => 'everywhere', 'exclude_post_ids' => '', 'exclude_categories' => array(), // New installs get the officially-integrated flow with our own design // kept intact. Updating installs have no 'implementation_method' saved, // and every consumer falls back to 'legacy', so their behaviour is unchanged. 'implementation_method' => 'advanced', 'standard_theme' => 'light', 'standard_lang' => 'auto', 'advanced_lang' => 'auto', // Defaults for manual placements: the [preferred_source] shortcode, // the editor block, and the adasprso_preferred_source() template tag. 'shortcode_style' => 'default', 'shortcode_align' => 'center', 'shortcode_text' => 'Stay connected via Google News', 'shortcode_subtitle' => 'Follow us for the latest travel updates and guides.', 'shortcode_link_prefix' => 'Enjoyed this article? You can', 'shortcode_link_suffix' => 'to see more from us.', 'shortcode_bg_color' => '#ffffff', 'shortcode_text_color' => '#1c1e21', 'shortcode_skip_auto_inline' => 1, ); add_option('adasprso_options', $default_options); // Record activation date for the review notice (only on first activation). if ( false === get_option( 'adasprso_activation_date' ) ) { add_option( 'adasprso_activation_date', time() ); } } register_activation_hook(__FILE__, 'adasprso_activate'); /** * The code that runs during plugin deactivation. */ function adasprso_deactivate() { // Nothing specific needed on deactivation } register_deactivation_hook(__FILE__, 'adasprso_deactivate'); /** * The core plugin class. */ class ADASPRSO_Main { /** * The unique identifier of this plugin. */ protected $plugin_name; /** * The current version of the plugin. */ protected $version; /** * Plugin options */ protected $options; /** * The public-facing class instance, shared by the hooks, the shortcode, * the block, and the adasprso_preferred_source() template tag. * * @var ADASPRSO_Public */ protected $public; /** * Initialize the class and set its properties. */ public function __construct() { $this->plugin_name = ADASPRSO_PLUGIN_NAME; $this->version = ADASPRSO_VERSION; $this->options = get_option('adasprso_options'); $this->load_dependencies(); $this->define_admin_hooks(); $this->define_public_hooks(); } /** * Load the required dependencies for this plugin. * * Admin-only classes are skipped on front-end requests. AJAX requests go * through admin-ajax.php where is_admin() is true, so the AJAX handlers * registered by these classes (including the analytics tracking endpoint) * keep working. */ private function load_dependencies() { // Include public class require_once ADASPRSO_PLUGIN_PATH . 'public/class-add-as-preferred-source-public.php'; if ( is_admin() ) { // Include admin class require_once ADASPRSO_PLUGIN_PATH . 'admin/class-add-as-preferred-source-admin.php'; // Include admin notices, deactivation feedback, and analytics classes require_once ADASPRSO_PLUGIN_PATH . 'includes/class-aaps-admin-notices.php'; require_once ADASPRSO_PLUGIN_PATH . 'includes/class-aaps-deactivation-feedback.php'; require_once ADASPRSO_PLUGIN_PATH . 'includes/class-aaps-analytics.php'; } } /** * Register all of the hooks related to the admin area functionality. */ private function define_admin_hooks() { if ( ! is_admin() ) { return; } // Backfill install date for users who activated before this option existed. if ( false === get_option( 'adasprso_activation_date' ) ) { add_option( 'adasprso_activation_date', time() ); } $plugin_admin = new ADASPRSO_Admin($this->get_plugin_name(), $this->get_version(), $this->options); // Add settings link to plugin add_filter('plugin_action_links_' . plugin_basename(__FILE__), array($plugin_admin, 'add_action_links')); // Admin notice add_action('admin_notices', array($plugin_admin, 'admin_notice')); // Admin menu add_action('admin_menu', array($plugin_admin, 'add_menu_page')); // Register settings add_action('admin_init', array($plugin_admin, 'register_settings')); // Admin scripts add_action('admin_enqueue_scripts', array($plugin_admin, 'enqueue_styles')); add_action('admin_enqueue_scripts', array($plugin_admin, 'enqueue_scripts')); // Review notice after 8 days new ADASPRSO_Admin_Notices(); // Deactivation feedback modal new ADASPRSO_Deactivation_Feedback( ADASPRSO_PLUGIN_URL, ADASPRSO_VERSION ); // Analytics tracking (registers AJAX handlers) new ADASPRSO_Analytics(); } /** * Register all of the hooks related to the public-facing functionality. */ private function define_public_hooks() { $plugin_public = new ADASPRSO_Public($this->get_plugin_name(), $this->get_version(), $this->options); $this->public = $plugin_public; // Public scripts add_action('wp_enqueue_scripts', array($plugin_public, 'enqueue_styles')); add_action('wp_enqueue_scripts', array($plugin_public, 'enqueue_scripts')); // The block's editor preview is the front-end markup, so it needs the // front-end stylesheet inside the editor canvas too. add_action('enqueue_block_assets', array($plugin_public, 'enqueue_block_editor_canvas_styles')); // Google's own preferred-source script (Advanced / Standard implementation methods) add_action('wp_head', array($plugin_public, 'render_google_publisher_script')); // Add banner to footer add_action('wp_footer', array($plugin_public, 'display_preferred_source_banner')); // Add inline button to content add_filter('the_content', array($plugin_public, 'add_inline_button_to_content')); // Manual placement: shortcode (plus a prefixed alias in case another // plugin already owns [preferred_source]) and the editor block. Both // are registered in the admin too, so the block's server-side preview // and shortcodes rendered through REST keep working. add_shortcode(ADASPRSO_Public::SHORTCODE_TAG, array($plugin_public, 'render_shortcode')); add_shortcode(ADASPRSO_Public::SHORTCODE_ALIAS, array($plugin_public, 'render_shortcode')); add_action('init', array($this, 'register_block')); } /** * Registers the editor block. Its markup comes from the same renderer as * the shortcode, so the two never drift apart. */ public function register_block() { // block.json-based registration needs WP 5.8; on 5.5-5.7 the metadata // helper does the same job. Older installs simply get no block - the // shortcode and the template tag still work everywhere. $can_register_from_path = function_exists( 'register_block_type' ) && version_compare( get_bloginfo( 'version' ), '5.8', '>=' ); $can_register_from_metadata = function_exists( 'register_block_type_from_metadata' ); if ( ! $can_register_from_path && ! $can_register_from_metadata ) { return; } // block.json points its "style" at this handle, so it has to exist by // the time the block is registered - that is what loads the stylesheet // into the editor canvas as well as the front end. $this->public->register_public_style(); // Registered by hand rather than through block.json's "file:" syntax // so the editor dependencies are explicit — the plugin ships no build // step, so there is no generated asset file to read them from. wp_register_script( 'adasprso-preferred-source-block', ADASPRSO_PLUGIN_URL . 'blocks/preferred-source/editor.js', array( 'wp-blocks', 'wp-element', 'wp-block-editor', 'wp-components', 'wp-i18n', 'wp-server-side-render' ), ADASPRSO_VERSION, true ); $args = array( 'render_callback' => array( $this->public, 'render_block' ) ); if ( $can_register_from_path ) { register_block_type( ADASPRSO_PLUGIN_PATH . 'blocks/preferred-source', $args ); } else { register_block_type_from_metadata( ADASPRSO_PLUGIN_PATH . 'blocks/preferred-source', $args ); } } /** * The public-facing class instance. * * @return ADASPRSO_Public */ public function get_public() { return $this->public; } /** * The name of the plugin used to uniquely identify it within the context of * WordPress and to define internationalization functionality. */ public function get_plugin_name() { return $this->plugin_name; } /** * Retrieve the version number of the plugin. */ public function get_version() { return $this->version; } } /** * Admin footer text only on the settings page */ function adasprso_admin_footer_text( $text ) { global $pagenow; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Only checking current page, no form processing if ( 'options-general.php' === $pagenow && isset( $_GET['page'] ) && sanitize_text_field( wp_unslash( $_GET['page'] ) ) === 'add-as-preferred-source' ) { $link = '' . esc_html__( 'a ★★★★★ rating', 'add-as-preferred-source' ) . ''; return wp_kses( sprintf( /* translators: %s: link to the plugin review page */ __( 'Thank you for using the Add as Preferred Source plugin :) If you like it, please leave %s to support us on WordPress.org to help us spread the word to the community.', 'add-as-preferred-source' ), $link ), array( 'a' => array( 'href' => array(), 'target' => array(), 'rel' => array(), ), ) ); } return $text; } add_filter('admin_footer_text', 'adasprso_admin_footer_text'); /** * Template tag: render the preferred-source button anywhere in a theme. * * 'pill' ) ); ?> * * Accepts the same options as the [preferred_source] shortcode: style, text, * subtitle, link_prefix, link_suffix, bg_color, text_color, align, class. * Anything omitted falls back to the Shortcode tab settings. * * @since 1.3.0 * @param array $args Optional. Overrides for the saved settings. * @param bool $echo Optional. Whether to echo the markup. Default true. * @return string The button HTML. */ function adasprso_preferred_source( $args = array(), $echo = true ) { $plugin = adasprso_main(); $public = $plugin ? $plugin->get_public() : null; if ( ! $public ) { return ''; } $html = $public->render_button( array_merge( (array) $args, array( 'context' => 'template' ) ) ); if ( $echo ) { echo $html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- built and escaped in ADASPRSO_Public::render_button() } return $html; } /** * The plugin instance, so the template tag can reach the public class. * * @return ADASPRSO_Main */ function adasprso_main() { static $instance = null; if ( null === $instance ) { $instance = new ADASPRSO_Main(); } return $instance; } /** * Begins execution of the plugin. */ function adasprso_run() { adasprso_main(); } add_action( 'plugins_loaded', 'adasprso_run' );