PluginProbe
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO / 2.10.0
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO v2.10.0
2.11.0 2.10.0 2.9.0 2.8.0 2.7.0 2.6.0 2.5.0 2.4.0 2.3.0 2.2.0 2.1.1 2.1.0 2.0.2 2.0.1 2.0.0 1.32.0 1.31.0 1.30.0 1.29.0 1.28.0 1.27.0 1.26.0 1.25.0 trunk 1.0.0 All 52 releases
← All changes | includes/seo/class-site-identity-manager.php +94 -22 2.9.0 → 2.10.0 View file →
@@ -1541,11 +1541,12 @@
1541 1541 $optimization['score'] -= 15;
1542 1542 }
1543 1543 }
1544 1544
1545 - // Business type validation
1546 - if (empty($settings['business_type'])) {
1547 - $optimization['suggestions'][] = 'Select a specific business type for better schema markup';
1545 + // Business type validation (shared rule, one message — #622).
1546 + $business_type = $this->business_type_status($settings);
1547 + if ('suggestion' === $business_type['status']) {
1548 + $optimization['suggestions'][] = $business_type['message'];
1548 1549 $optimization['score'] -= 5;
1549 1550 }
1550 1551
1551 1552 // Email validation
@@ -2075,24 +2076,17 @@
2075 2076 'icon' => '✗'
2076 2077 ];
2077 2078 }
2078 2079
2079 - // Business Type validation
2080 - if (!empty($settings['business_type']) && $settings['business_type'] !== 'LocalBusiness') {
2081 - $field_details[] = [
2082 - 'field' => 'business_type',
2083 - 'label' => 'Business type is selected for proper schema markup.',
2084 - 'status' => 'valid',
2085 - 'icon' => '✓'
2086 - ];
2087 - } else {
2088 - $field_details[] = [
2089 - 'field' => 'business_type',
2090 - 'label' => 'Specific business type selection recommended for better schema markup.',
2091 - 'status' => 'suggestion',
2092 - 'icon' => '⚠'
2093 - ];
2094 - }
2080 + // Business Type validation — see business_type_status() for why there
2081 + // is exactly one rule here now (#622).
2082 + $business_type = $this->business_type_status($settings);
2083 + $field_details[] = [
2084 + 'field' => 'business_type',
2085 + 'label' => $business_type['message'],
2086 + 'status' => $business_type['status'],
2087 + 'icon' => 'valid' === $business_type['status'] ? '✓' : '⚠',
2088 + ];
2095 2089
2096 2090 // Address validation (NAP consistency)
2097 2091 $address_fields = ['business_address', 'business_city', 'business_state', 'business_country'];
2098 2092 $address_complete = true;
@@ -2776,11 +2770,15 @@
2776 2770 } else {
2777 2771 $validation['suggestions'][] = 'Add business hours to improve local search visibility';
2778 2772 }
2779 2773
2780 - // Validate business type
2781 - if (empty($settings['business_type'])) {
2782 - $validation['suggestions'][] = 'Select a specific business type for better schema markup';
2774 + // Business type, through the shared rule (#622). This is the only place
2775 + // it is reported on the generic path: validate_settings() with no tab
2776 + // context attaches basic-info field details, not business-info ones, so
2777 + // without this the setting would go unreported there entirely.
2778 + $business_type = $this->business_type_status($settings);
2779 + if ('suggestion' === $business_type['status']) {
2780 + $validation['suggestions'][] = $business_type['message'];
2783 2781 }
2784 2782
2785 2783 return $validation;
2786 2784 }
@@ -2973,9 +2971,83 @@
2973 2971 ? $sanitized['canonical_scheme']
2974 2972 : Url_Scheme::AUTOMATIC;
2975 2973 }
2976 2974
2975 + // Same reasoning again for the business type. It goes straight into
2976 + // LocalBusiness schema, so a type that is not in the schema.org
2977 + // vocabulary is invalid structured data — and storing it verbatim would
2978 + // have get-site-identity-settings report a type the site cannot
2979 + // actually publish. An empty value keeps meaning "not set"; anything
2980 + // else unrecognised falls back to the general-purpose root (#623).
2981 + if (array_key_exists('business_type', $sanitized)) {
2982 + $type = (string) $sanitized['business_type'];
2983 +
2984 + if ('' !== $type && !\ThinkRank\Config\Local_Business_Types_Config::is_valid($type)) {
2985 + $type = \ThinkRank\Config\Local_Business_Types_Config::ROOT;
2986 + }
2987 +
2988 + $sanitized['business_type'] = $type;
2989 + }
2990 +
2977 2991 return $sanitized;
2992 + }
2993 +
2994 + /**
2995 + * schema.org's general-purpose LocalBusiness type.
2996 + *
2997 + * The default, the first option in the control, and a valid answer in its
2998 + * own right — which is the whole point of #622.
2999 + *
3000 + * @since 2.10.0
3001 + * @var string
3002 + */
3003 + private const GENERAL_BUSINESS_TYPE = 'LocalBusiness';
3004 +
3005 + /**
3006 + * The one rule for whether a business type needs the user's attention.
3007 + *
3008 + * There were three, with two wordings and two different conditions. Two
3009 + * fired when the value was empty; the third fired when it WAS
3010 + * `LocalBusiness` — which is the default, the first option in the control
3011 + * and a perfectly valid schema.org type. So the warning appeared out of the
3012 + * box for every site, could not be cleared without choosing a type that
3013 + * might be inaccurate, and on an empty value it appeared three times in two
3014 + * different phrasings, which is why it was reported as showing twice (#622).
3015 + *
3016 + * The rule now: a type is expected, and any type in the vocabulary is a
3017 + * correct answer. Only an unset value is worth prompting about.
3018 + * `LocalBusiness` is the general-purpose answer and is accepted as one —
3019 + * with a note that a more specific type sharpens the schema, phrased as the
3020 + * guidance it is rather than as a fault the user has to clear.
3021 + *
3022 + * @since 2.10.0
3023 + *
3024 + * @param array $settings Site identity settings.
3025 + * @return array{status:string,message:string} `valid` or `suggestion`.
3026 + */
3027 + private function business_type_status(array $settings): array {
3028 + $type = trim((string) ($settings['business_type'] ?? ''));
3029 +
3030 + if ('' === $type) {
3031 + return [
3032 + 'status' => 'suggestion',
3033 + 'message' => __('Select a business type so your local schema describes the right kind of business.', 'thinkrank'),
3034 + ];
3035 + }
3036 +
3037 + // The literal rather than a constant from the expanded type list (#623):
3038 + // that lands on its own branch, and this fix must not wait on it.
3039 + if (self::GENERAL_BUSINESS_TYPE === $type) {
3040 + return [
3041 + 'status' => 'valid',
3042 + 'message' => __('Business type is set to Local Business. A more specific type sharpens your schema, if one fits.', 'thinkrank'),
3043 + ];
3044 + }
3045 +
3046 + return [
3047 + 'status' => 'valid',
3048 + 'message' => __('Business type is selected for proper schema markup.', 'thinkrank'),
3049 + ];
2978 3050 }
2979 3051
2980 3052 /**
2981 3053 * Get default settings for a context type (implements interface)