| @@ -1,0 +1,290 @@ | ||
| 1 | +<?php | |
| 2 | +/* | |
| 3 | + * License: GPLv3 | |
| 4 | + * License URI: https://www.gnu.org/licenses/gpl.txt | |
| 5 | + * Copyright 2012-2026 Jean-Sebastien Morisset (https://wpsso.com/) | |
| 6 | + */ | |
| 7 | + | |
| 8 | +if ( ! defined( 'ABSPATH' ) ) { | |
| 9 | + | |
| 10 | + die( 'These aren\'t the droids you\'re looking for.' ); | |
| 11 | +} | |
| 12 | + | |
| 13 | +if ( ! defined( 'WPSSO_PLUGINDIR' ) ) { | |
| 14 | + | |
| 15 | + die( 'Do. Or do not. There is no try.' ); | |
| 16 | +} | |
| 17 | + | |
| 18 | +if ( ! class_exists( 'WpssoAdminHeadSuggestAddons' ) ) { | |
| 19 | + | |
| 20 | + class WpssoAdminHeadSuggestAddons { | |
| 21 | + | |
| 22 | + private $p; // Wpsso class object. | |
| 23 | + | |
| 24 | + /* | |
| 25 | + * Instantiated by WpssoAdminHeadSuggest->__construct(). | |
| 26 | + */ | |
| 27 | + public function __construct( &$plugin ) { | |
| 28 | + | |
| 29 | + $this->p =& $plugin; | |
| 30 | + } | |
| 31 | + | |
| 32 | + public function suggest( $suggest_max = 2 ) { | |
| 33 | + | |
| 34 | + if ( $this->p->debug->enabled ) { | |
| 35 | + | |
| 36 | + $this->p->debug->log_args( array( | |
| 37 | + 'suggest_max' => $suggest_max, | |
| 38 | + ) ); | |
| 39 | + } | |
| 40 | + | |
| 41 | + $suggested = 0; | |
| 42 | + | |
| 43 | + if ( ! current_user_can( 'install_plugins' ) ) return $suggested; | |
| 44 | + | |
| 45 | + /* | |
| 46 | + * Suggest update manager, woocommerce, sitemaps addons, in that order. | |
| 47 | + */ | |
| 48 | + foreach ( array( 'update_manager', 'woocommerce', 'sitemaps' ) as $suffix ) { | |
| 49 | + | |
| 50 | + $methodname = 'suggest_addons_' . $suffix; | |
| 51 | + $suggested = $suggested + $this->$methodname( $suggest_max - $suggested ); | |
| 52 | + | |
| 53 | + if ( $this->p->debug->enabled ) { | |
| 54 | + | |
| 55 | + $this->p->debug->log( $methodname . ' suggested = ' . $suggested ); | |
| 56 | + } | |
| 57 | + | |
| 58 | + if ( $suggested >= $suggest_max ) break; | |
| 59 | + } | |
| 60 | + | |
| 61 | + if ( $this->p->debug->enabled ) { | |
| 62 | + | |
| 63 | + $this->p->debug->log( 'return suggested = ' . $suggested ); | |
| 64 | + } | |
| 65 | + | |
| 66 | + return $suggested; | |
| 67 | + } | |
| 68 | + | |
| 69 | + private function suggest_addons_update_manager( $suggest_max ) { | |
| 70 | + | |
| 71 | + $pkg_info = $this->p->util->get_pkg_info(); // Uses a local cache. | |
| 72 | + $um_info = $this->p->cf[ 'plugin' ][ 'wpssoum' ]; | |
| 73 | + $have_tid = false; | |
| 74 | + $suggested = 0; | |
| 75 | + | |
| 76 | + foreach ( $this->p->cf[ 'plugin' ] as $ext => $ext_info ) { | |
| 77 | + | |
| 78 | + if ( empty( $ext_info[ 'base' ] ) ) continue; // Just in case. | |
| 79 | + | |
| 80 | + if ( empty( $this->p->options[ 'plugin_' . $ext . '_tid' ] ) ) continue; | |
| 81 | + | |
| 82 | + $have_tid = true; // Found at least one plugin with an auth id. | |
| 83 | + | |
| 84 | + if ( empty( $um_info[ 'version' ] ) ) break; // Update manager is not active. | |
| 85 | + | |
| 86 | + if ( ! empty( $pkg_info[ $ext ][ 'pdir' ] ) ) continue; // Already updated to Pro. | |
| 87 | + | |
| 88 | + if ( SucomPlugin::is_plugin_installed( $ext_info[ 'base' ] ) ) { | |
| 89 | + | |
| 90 | + $this->p->notice->warn( $this->p->msgs->get( 'notice-pro-not-updated', array( 'plugin_id' => $ext ) ) ); | |
| 91 | + | |
| 92 | + } else $this->p->notice->warn( $this->p->msgs->get( 'notice-pro-not-installed', array( 'plugin_id' => $ext ) ) ); | |
| 93 | + | |
| 94 | + if ( ++$suggested >= $suggest_max ) return $suggested; | |
| 95 | + } | |
| 96 | + | |
| 97 | + if ( $have_tid ) { // One or more auth ids have been found. | |
| 98 | + | |
| 99 | + if ( empty( $um_info[ 'version' ] ) || ! class_exists( 'WpssoUm' ) ) { // Update manager is not active. | |
| 100 | + | |
| 101 | + if ( SucomPlugin::is_plugin_installed( $um_info[ 'base' ] ) ) { // Update manager is installed. | |
| 102 | + | |
| 103 | + $this->p->notice->warn( $this->p->msgs->get( 'notice-um-activate-add-on' ) ); | |
| 104 | + | |
| 105 | + } else $this->p->notice->warn( $this->p->msgs->get( 'notice-um-add-on-required' ) ); // Update manager is not installed. | |
| 106 | + | |
| 107 | + if ( ++$suggested >= $suggest_max ) return $suggested; | |
| 108 | + | |
| 109 | + } else { | |
| 110 | + | |
| 111 | + $um_rec_ver = WpssoConfig::$cf[ 'um' ][ 'rec_version' ]; | |
| 112 | + $um_min_ver = WpssoConfig::$cf[ 'um' ][ 'min_version' ]; | |
| 113 | + | |
| 114 | + if ( version_compare( $um_info[ 'version' ], $um_rec_ver, '<' ) ) { | |
| 115 | + | |
| 116 | + if ( version_compare( $um_info[ 'version' ], $um_min_ver, '<' ) ) { | |
| 117 | + | |
| 118 | + $this->p->notice->err( $this->p->msgs->get( 'notice-um-update-required' ) ); | |
| 119 | + | |
| 120 | + } else $this->p->notice->warn( $this->p->msgs->get( 'notice-um-update-recommended' ) ); | |
| 121 | + | |
| 122 | + if ( ++$suggested >= $suggest_max ) return $suggested; | |
| 123 | + } | |
| 124 | + } | |
| 125 | + } | |
| 126 | + | |
| 127 | + return $suggested; | |
| 128 | + } | |
| 129 | + | |
| 130 | + private function suggest_addons_woocommerce( $suggest_max ) { | |
| 131 | + | |
| 132 | + $suggested = 0; | |
| 133 | + | |
| 134 | + if ( empty( $this->p->avail[ 'ecom' ][ 'woocommerce' ] ) ) return $suggested; // WooCommerce is not active. | |
| 135 | + | |
| 136 | + if ( empty( $this->p->avail[ 'p' ][ 'schema' ] ) ) return $suggested; // Schema markup is disabled. | |
| 137 | + | |
| 138 | + // translators: Please ignore - translation uses a different text domain. | |
| 139 | + $ecom_plugin_name = __( 'WooCommerce', 'woocommerce' ); | |
| 140 | + | |
| 141 | + foreach ( array( 'wcmd', 'wcsdt', 'gmf', 'mrp', 'cmcf' ) as $p_ext ) { | |
| 142 | + | |
| 143 | + $ext = 'wpsso' . $p_ext; | |
| 144 | + $notice_key = 'suggest-' . $ext. '-for-woocommerce'; | |
| 145 | + | |
| 146 | + if ( ! empty( $this->p->avail[ 'p_ext' ][ $p_ext ] ) ) continue; | |
| 147 | + | |
| 148 | + if ( ! $this->p->notice->is_admin_pre_notices( $notice_key ) ) continue; | |
| 149 | + | |
| 150 | + $notice_msg = ''; | |
| 151 | + $action_links = array(); // Init a new action array for the notice message. | |
| 152 | + $ext_info = $this->p->cf[ 'plugin' ][ $ext ]; | |
| 153 | + $ext_name_transl = _x( $ext_info[ 'name' ], 'plugin name', 'wpsso' ); | |
| 154 | + $ext_addons_link = $this->p->util->get_admin_url( 'addons#' . $ext, $ext_name_transl ); | |
| 155 | + | |
| 156 | + if ( $install_activate_link = $this->get_install_activate_addon_link( $ext ) ) { | |
| 157 | + | |
| 158 | + $action_links[] = $install_activate_link; | |
| 159 | + } | |
| 160 | + | |
| 161 | + switch ( $p_ext ) { | |
| 162 | + | |
| 163 | + case 'cmcf': | |
| 164 | + | |
| 165 | + $notice_msg = sprintf( __( 'If you advertise or sell items on Facebook and Instagram, the %s add-on can provide a product feed for Meta\'s Commerce Manager.', 'wpsso' ), $ext_name_transl ) . ' '; | |
| 166 | + | |
| 167 | + $notice_msg .= sprintf( __( 'You should activate the %s add-on if you don\'t already have a plugin to manage your Commerce Manager product feed XML.', 'wpsso' ), $ext_addons_link ) . ' '; | |
| 168 | + | |
| 169 | + break; | |
| 170 | + | |
| 171 | + case 'gmf': | |
| 172 | + | |
| 173 | + $notice_msg = sprintf( __( 'If you have created an account with Google Merchant Center, the %s add-on can provide a product feed for Google Merchant Center.', 'wpsso' ), $ext_name_transl ) . ' '; | |
| 174 | + | |
| 175 | + $notice_msg .= sprintf( __( 'You should activate the %s add-on if you don\'t already have a plugin to manage your Google merchant feed XML.', 'wpsso' ), $ext_addons_link ) . ' '; | |
| 176 | + | |
| 177 | + break; | |
| 178 | + | |
| 179 | + case 'mrp': | |
| 180 | + | |
| 181 | + $notice_msg = __( 'Google suggests including a merchant return policy in Schema Product offers markup.', 'wpsso' ) . ' '; | |
| 182 | + | |
| 183 | + $notice_msg .= sprintf( __( 'If you have not created a return policy in Google Merchant Center, you should activate the %s add-on to manage return policies and select a return policy for your product offers.', 'wpsso' ), $ext_addons_link ) . ' '; | |
| 184 | + | |
| 185 | + break; | |
| 186 | + | |
| 187 | + case 'wcmd': | |
| 188 | + | |
| 189 | + if ( ! empty( $this->p->avail[ 'ecom' ][ 'woo-add-gtin' ] ) || | |
| 190 | + ! empty( $this->p->avail[ 'ecom' ][ 'wpm-product-gtin-wc' ] ) ) continue 2; // Get another $ext. | |
| 191 | + | |
| 192 | + $notice_msg = __( 'Google requires at least one unique product identifier for Schema Product markup, like the product MPN (Manufacturer Part Number), UPC, EAN, GTIN, or ISBN.', 'wpsso' ) . ' '; | |
| 193 | + | |
| 194 | + $notice_msg .= sprintf( __( 'The product SKU (Stock Keeping Unit) from %s is not a unique product identifier.', | |
| 195 | + 'wpsso' ), $ecom_plugin_name ) . ' '; | |
| 196 | + | |
| 197 | + $notice_msg .= sprintf( __( 'You should activate the %s add-on if you don\'t already have a plugin to manage unique product identifiers for WooCommerce.', 'wpsso' ), $ext_addons_link ) . ' '; | |
| 198 | + | |
| 199 | + break; | |
| 200 | + | |
| 201 | + case 'wcsdt': | |
| 202 | + | |
| 203 | + $shipping_continents = WC()->countries->get_shipping_continents(); // Since WC v3.6.0. | |
| 204 | + $shipping_countries = WC()->countries->get_shipping_countries(); | |
| 205 | + $shipping_enabled = $shipping_continents || $shipping_countries ? true : false; | |
| 206 | + | |
| 207 | + if ( ! $shipping_enabled ) continue 2; // Get another $ext. | |
| 208 | + | |
| 209 | + $notice_msg = sprintf( __( 'Product shipping features are enabled in %1$s but the %2$s add-on is not active.', | |
| 210 | + 'wpsso' ), $ecom_plugin_name, $ext_name_transl ) . ' '; | |
| 211 | + | |
| 212 | + $notice_msg .= __( 'Adding shipping details to your Schema Product markup is important if you offer free or low-cost shipping options, as this will make your products more appealing in Google search results.', 'wpsso' ) . ' '; | |
| 213 | + | |
| 214 | + break; | |
| 215 | + } | |
| 216 | + | |
| 217 | + if ( ! empty( $notice_msg ) ) { | |
| 218 | + | |
| 219 | + $notice_msg .= SucomUtil::array_to_list_html( $action_links ); | |
| 220 | + | |
| 221 | + $this->p->notice->warn( $notice_msg, null, $notice_key, $dismiss_time = true ); | |
| 222 | + | |
| 223 | + if ( ++$suggested >= $suggest_max ) return $suggested; | |
| 224 | + } | |
| 225 | + } | |
| 226 | + | |
| 227 | + return $suggested; | |
| 228 | + } | |
| 229 | + | |
| 230 | + private function suggest_addons_sitemaps( $suggest_max ) { | |
| 231 | + | |
| 232 | + $suggested = 0; | |
| 233 | + $notice_key = 'suggest-wpssowpsm'; | |
| 234 | + | |
| 235 | + if ( ! empty( $this->p->avail[ 'p_ext' ][ 'wpsm' ] ) ) return $suggested; // Already active. | |
| 236 | + | |
| 237 | + if ( SucomUtilWP::sitemaps_disabled() ) return $suggested; | |
| 238 | + | |
| 239 | + if ( $this->p->util->robots->is_disabled() ) return $suggested; | |
| 240 | + | |
| 241 | + if ( ! $this->p->notice->is_admin_pre_notices( $notice_key ) ) return $suggested; | |
| 242 | + | |
| 243 | + $action_links = array(); // Init a new action array for the notice message. | |
| 244 | + | |
| 245 | + if ( $install_activate_link = $this->get_install_activate_addon_link( 'wpssowpsm' ) ) { | |
| 246 | + | |
| 247 | + $action_links[] = $install_activate_link; | |
| 248 | + } | |
| 249 | + | |
| 250 | + $ext_info = $this->p->cf[ 'plugin' ][ 'wpssowpsm' ]; | |
| 251 | + $ext_name_transl = _x( $ext_info[ 'name' ], 'plugin name', 'wpsso' ); | |
| 252 | + $sitemaps_url = get_site_url( $blog_id = null, $path = '/wp-sitemap.xml' ); | |
| 253 | + | |
| 254 | + $notice_msg = sprintf( __( 'The <a href="%1$s">WordPress sitemaps XML</a> is enabled, but the %2$s add-on is not active.', | |
| 255 | + 'wpsso' ), $sitemaps_url, $ext_name_transl ) . ' '; | |
| 256 | + | |
| 257 | + $notice_msg .= __( 'You can activate this add-on to manage post and taxonomy types included in the sitemaps XML, exclude posts, pages, custom post types, taxonomy terms (categories, tags, etc.), and/or user profiles, enhance the sitemaps XML with article modification times, images sitemaps, news sitemaps and more.', 'wpsso' ); | |
| 258 | + | |
| 259 | + $notice_msg .= SucomUtil::array_to_list_html( $action_links ); | |
| 260 | + | |
| 261 | + $this->p->notice->inf( $notice_msg, null, $notice_key, $dismiss_time = true ); | |
| 262 | + | |
| 263 | + return ++$suggested; | |
| 264 | + } | |
| 265 | + | |
| 266 | + private function get_install_activate_addon_link( $ext ) { | |
| 267 | + | |
| 268 | + if ( empty( $this->p->cf[ 'plugin' ][ $ext ][ 'base' ] ) ) { // Just in case. | |
| 269 | + | |
| 270 | + return false; | |
| 271 | + } | |
| 272 | + | |
| 273 | + $ext_info = $this->p->cf[ 'plugin' ][ $ext ]; | |
| 274 | + $ext_name_transl = _x( $ext_info[ 'name' ], 'plugin name', 'wpsso' ); | |
| 275 | + | |
| 276 | + if ( SucomPlugin::is_plugin_installed( $ext_info[ 'base' ] ) ) { | |
| 277 | + | |
| 278 | + $search_url = is_multisite() ? network_admin_url( 'plugins.php', null ) : get_admin_url( $blog_id = null, 'plugins.php' ); | |
| 279 | + $search_url = add_query_arg( array( 's' => $ext_info[ 'slug' ] ), $search_url ); | |
| 280 | + | |
| 281 | + return '<a href="' . $search_url . '">' . sprintf( __( 'Activate the %s add-on.', 'wpsso' ), $ext_name_transl ) . '</a>'; | |
| 282 | + | |
| 283 | + } | |
| 284 | + | |
| 285 | + $addons_url = $this->p->util->get_admin_url( 'addons#' . $ext ); | |
| 286 | + | |
| 287 | + return '<a href="' . $addons_url . '">' . sprintf( __( 'Install and activate the %s add-on.', 'wpsso' ), $ext_name_transl ) . '</a>'; | |
| 288 | + } | |
| 289 | + } | |
| 290 | +} | |