| @@ -71,8 +71,9 @@ | ||
| 71 | 71 | 'thinkrank_author_archives', |
| 72 | 72 | 'thinkrank_content_tools', |
| 73 | 73 | 'thinkrank_ai_insights', |
| 74 | 74 | 'thinkrank_internal_links', |
| 75 | + 'thinkrank_external_links', | |
| 75 | 76 | 'thinkrank_redirections', |
| 76 | 77 | 'thinkrank_broken_links', |
| 77 | 78 | 'thinkrank_woocommerce', |
| 78 | 79 | 'thinkrank_settings', |
| @@ -116,8 +117,9 @@ | ||
| 116 | 117 | 'thinkrank_author_archives' => __('Author Archives', 'thinkrank'), |
| 117 | 118 | 'thinkrank_content_tools' => __('AI Tools', 'thinkrank'), |
| 118 | 119 | 'thinkrank_ai_insights' => __('AI Insights', 'thinkrank'), |
| 119 | 120 | 'thinkrank_internal_links' => __('Internal Links', 'thinkrank'), |
| 121 | + 'thinkrank_external_links' => __('External Links', 'thinkrank'), | |
| 120 | 122 | 'thinkrank_redirections' => __('Redirections', 'thinkrank'), |
| 121 | 123 | 'thinkrank_broken_links' => __('Broken Links', 'thinkrank'), |
| 122 | 124 | 'thinkrank_woocommerce' => __('WooCommerce', 'thinkrank'), |
| 123 | 125 | 'thinkrank_settings' => __('Settings & API Keys', 'thinkrank'), |
| @@ -155,8 +157,9 @@ | ||
| 155 | 157 | 'instant-indexing' => 'thinkrank_instant_indexing', |
| 156 | 158 | 'author-archives' => 'thinkrank_author_archives', |
| 157 | 159 | 'ai-insights' => 'thinkrank_ai_insights', |
| 158 | 160 | 'internal-links' => 'thinkrank_internal_links', |
| 161 | + 'external-links' => 'thinkrank_external_links', | |
| 159 | 162 | 'redirections' => 'thinkrank_redirections', |
| 160 | 163 | 'broken-links' => 'thinkrank_broken_links', |
| 161 | 164 | 'woocommerce' => 'thinkrank_woocommerce', |
| 162 | 165 | 'integrations' => 'thinkrank_settings', |
| @@ -195,14 +198,15 @@ | ||
| 195 | 198 | 'global-seo' => 'thinkrank_global_seo', |
| 196 | 199 | 'global-robot-meta' => 'thinkrank_crawling', |
| 197 | 200 | 'image-seo' => 'thinkrank_image_seo', |
| 198 | 201 | 'ai-insights' => 'thinkrank_ai_insights', |
| 199 | - // Brand Visibility is part of the AI Insights section. | |
| 200 | - 'brand-visibility' => 'thinkrank_ai_insights', | |
| 201 | 202 | 'schema' => 'thinkrank_schema', |
| 202 | 203 | // Custom Schema (Pro) lives in the Schema Manager section but |
| 203 | 204 | // registers its own /custom-schema/ prefix. |
| 204 | 205 | 'custom-schema' => 'thinkrank_schema', |
| 206 | + // Custom Field Mapping (Pro) also lives in the Schema Manager | |
| 207 | + // section and registers its own /field-mapping/ prefix. | |
| 208 | + 'field-mapping' => 'thinkrank_schema', | |
| 205 | 209 | 'social-media' => 'thinkrank_social_media', |
| 206 | 210 | 'social-platforms' => 'thinkrank_settings', |
| 207 | 211 | 'sitemap' => 'thinkrank_crawling', |
| 208 | 212 | // Publisher Sitemaps (Pro) is part of the Crawling & AI Indexing |
| @@ -211,8 +215,9 @@ | ||
| 211 | 215 | 'llms-txt' => 'thinkrank_crawling', |
| 212 | 216 | 'instant-indexing' => 'thinkrank_instant_indexing', |
| 213 | 217 | 'author-archives' => 'thinkrank_author_archives', |
| 214 | 218 | 'internal-links' => 'thinkrank_internal_links', |
| 219 | + 'external-links' => 'thinkrank_external_links', | |
| 215 | 220 | 'redirections' => 'thinkrank_redirections', |
| 216 | 221 | 'broken-links' => 'thinkrank_broken_links', |
| 217 | 222 | 'woocommerce' => 'thinkrank_woocommerce', |
| 218 | 223 | // Multi-location (Pro) is managed inside Site Identity › Business Info. |
| @@ -302,8 +307,14 @@ | ||
| 302 | 307 | * @param string $route Full REST route (e.g. /thinkrank/v1/schema/...). |
| 303 | 308 | * @return string |
| 304 | 309 | */ |
| 305 | 310 | public static function capability_for_route(string $route): string { |
| 311 | + // Routes match case-insensitively in WP_REST_Server, and every key in | |
| 312 | + // route_map() and settings_category_map() is lowercase, so a section | |
| 313 | + // spelled /SiteMap/ must resolve to the same capability as /sitemap/ | |
| 314 | + // rather than fall back to the base access cap (#975). | |
| 315 | + $route = strtolower($route); | |
| 316 | + | |
| 306 | 317 | // Settings-management categories resolve by category rather than by |
| 307 | 318 | // prefix — see settings_category_map() for why this one route differs. |
| 308 | 319 | if (preg_match('#/thinkrank(?:-pro)?/v1/settings-management/category/([a-zA-Z0-9_-]+)#', $route, $c)) { |
| 309 | 320 | return self::capability_for_settings_category($c[1]); |