@@ -113,7 +113,7 @@ public function render_review_notice( $footer_text ) {
113113 __ ( 'Enjoying %1$s? %2$s %3$s rating. Thank you for being so supportive! ' , 'visualizer ' ),
114114 '<b>Visualizer</b> ' ,
115115 esc_html__ ( 'You can help us by leaving a ' , 'visualizer ' ),
116- '<a href="https://wordpress.org/support/plugin/visualizer/reviews/" target="_blank">★★★★★</a> '
116+ '<a href="https://wordpress.org/support/plugin/visualizer/reviews/#new-post " target="_blank">★★★★★</a> '
117117 );
118118 break ;
119119 }
@@ -427,7 +427,7 @@ public static function _getChartTypesLocalized( $enabledOnly = false, $get2Darra
427427 );
428428 }
429429
430- $ enabled = self ::proFeaturesLocked ();
430+ $ enabled = self ::proFeaturesEnabled ();
431431
432432 $ types = array_merge (
433433 $ additional ,
@@ -1163,6 +1163,20 @@ public function getPluginActionLinks( $links, $file ) {
11631163 * @return array Updated array of plugin meta links.
11641164 */
11651165 public function getPluginMetaLinks ( $ plugin_meta , $ plugin_file ) {
1166+ if ( Visualizer_Module::is_pro () ) {
1167+ return $ plugin_meta ;
1168+ }
1169+
1170+ // Also suppress the upsell when Pro is installed but not currently active.
1171+ if ( ! function_exists ( 'get_plugins ' ) ) {
1172+ require_once ABSPATH . 'wp-admin/includes/plugin.php ' ;
1173+ }
1174+ foreach ( array_keys ( get_plugins () ) as $ installed_plugin ) {
1175+ if ( false !== strpos ( $ installed_plugin , 'visualizer-pro ' ) ) {
1176+ return $ plugin_meta ;
1177+ }
1178+ }
1179+
11661180 if ( $ plugin_file === plugin_basename ( VISUALIZER_BASEFILE ) ) {
11671181 // knowledge base link
11681182 $ plugin_meta [] = sprintf (
@@ -1180,15 +1194,37 @@ public function getPluginMetaLinks( $plugin_meta, $plugin_file ) {
11801194 }
11811195
11821196 /**
1183- * If check is existing user.
1197+ * Returns true when premium chart types should be enabled for the current user.
11841198 *
1185- * @return bool Default false
1199+ * Pro 1.9.0+ hooks the 'visualizer_is_pro' filter and returns true only when
1200+ * the license is valid. Pre-1.9.0 Pro defined a Visualizer_Pro class instead;
1201+ * we detect that as a fallback so those legacy installs still work.
1202+ *
1203+ * Passing false as the filter default ensures the constant VISUALIZER_PRO
1204+ * (which is set to true whenever the Pro class exists, regardless of license
1205+ * state) cannot bypass the license check.
1206+ *
1207+ * @return bool
11861208 */
1187- public static function proFeaturesLocked () {
1188- if ( Visualizer_Module::is_pro () ) {
1209+ public static function proFeaturesEnabled () {
1210+ $ is_pro_filter = apply_filters ( 'visualizer_is_pro ' , false );
1211+
1212+ // Pro 1.9.0+: filter is hooked and returns true only with a valid license.
1213+ if ( $ is_pro_filter ) {
11891214 return true ;
11901215 }
1191- return 'yes ' === get_option ( 'visualizer-new-user ' , 'yes ' ) ? false : true ;
1216+
1217+ // Pro is installed (active) but the license check above did not pass.
1218+ // Do NOT fall through to the legacy "old user" path — that path exists
1219+ // only for sites that never had Pro installed. If Pro is present but
1220+ // the license is inactive we should lock, regardless of chart history.
1221+ if ( class_exists ( 'Visualizer_Pro ' , false ) ) {
1222+ return false ;
1223+ }
1224+
1225+ // No Pro installed at all: grant legacy access to existing users so
1226+ // their charts are not suddenly broken when they upgrade the free plugin.
1227+ return 'yes ' === get_option ( 'visualizer-new-user ' ) ? false : true ;
11921228 }
11931229
11941230 /**
0 commit comments