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.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 1.0.1 All 51 releases
thinkrank / includes / core / class-plan-config.php

class-plan-config.php in ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO 2.10.0, at includes/core/class-plan-config.php

276 lines 9.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Plan Config Class
5 *
6 * Single source of truth for free vs. pro capability gating across ThinkRank.
7 * Every freemium gate (REST validation, render pipeline, scheduler, mailer, UI)
8 * reads from here. No feature code should check `defined('THINKRANK_PRO_VERSION')`
9 * or `apply_filters('thinkrank_is_pro_active', ...)` directly — call these methods
10 * instead so a single override flips behavior everywhere.
11 *
12 * The Pro plugin attaches by filtering each feature's capability map. It never
13 * needs to fork or monkey-patch this file.
14 *
15 * @package ThinkRank\Core
16 * @since 1.9.0
17 */
18
19 declare(strict_types=1);
20
21 namespace ThinkRank\Core;
22
23 if (!defined('ABSPATH')) {
24 exit;
25 }
26
27 /**
28 * Plan_Config — capability registry for free/pro feature gating.
29 *
30 * Usage:
31 * if (Plan_Config::can('usage_policy', 'llms_txt')) { ... }
32 * $caps = Plan_Config::llms_txt();
33 *
34 * @since 1.9.0
35 */
36 final class Plan_Config {
37
38 /**
39 * Whether the Pro plugin is active.
40 *
41 * Resolves through `thinkrank_is_pro_active` so the Pro plugin (or a
42 * staging override) can flip the answer. Defaults to checking the
43 * `THINKRANK_PRO_VERSION` constant the Pro plugin defines on load.
44 */
45 public static function is_pro(): bool {
46 return (bool) apply_filters(
47 'thinkrank_is_pro_active',
48 defined('THINKRANK_PRO_VERSION')
49 );
50 }
51
52 /**
53 * Capability map for the llms.txt feature.
54 *
55 * Generating and editing llms.txt is FREE and stays free. What Pro adds is
56 * the usage policy: the `Training:` / `Summarization:` / `Embedding:` /
57 * `Require-Attribution:` directives that state what agents may do with the
58 * content, rather than describing the content itself (#160 in Pro).
59 *
60 * Schema:
61 * usage_policy bool May publish usage-policy directives in llms.txt.
62 * full_document bool May publish llms-full.txt, the full-content
63 * companion document (thinkrank-pro#171).
64 *
65 * @since 2.5.0
66 *
67 * @return array Capability map.
68 */
69 public static function llms_txt(): array {
70 $defaults = [
71 'usage_policy' => false,
72 'full_document' => false,
73 ];
74
75 /**
76 * Filter the llms.txt capability map.
77 *
78 * ThinkRank Pro sets `usage_policy` to true; nothing in the free
79 * plugin ever does, so the directives simply never render without it.
80 *
81 * @since 2.5.0
82 *
83 * @param array $defaults Capability map (see schema above).
84 */
85 $caps = apply_filters('thinkrank_llms_txt_capabilities', $defaults);
86
87 return array_merge($defaults, is_array($caps) ? $caps : []);
88 }
89
90 /**
91 * Capability map for the Site SEO Analyzer.
92 *
93 * Running the audit and seeing the score is FREE and stays free. What Pro
94 * adds is memory: dated snapshots of each run, a score trend, and a
95 * side-by-side comparison of two runs (#161 in Pro). Free keeps exactly
96 * what it has today — the most recent run, cached for an hour.
97 *
98 * Schema:
99 * history bool May persist and read audit snapshots.
100 * history_runs int Snapshots retained per site (0 = unlimited).
101 *
102 * @since 2.5.0
103 *
104 * @return array Capability map.
105 */
106 public static function seo_analyzer(): array {
107 $defaults = [
108 'history' => false,
109 'history_runs' => 0,
110 ];
111
112 /**
113 * Filter the SEO Analyzer capability map.
114 *
115 * ThinkRank Pro sets `history` to true and declares how many runs it
116 * retains. Nothing in the free plugin ever does, so no snapshot is
117 * ever written without Pro.
118 *
119 * @since 2.5.0
120 *
121 * @param array $defaults Capability map (see schema above).
122 */
123 $caps = apply_filters('thinkrank_seo_analyzer_capabilities', $defaults);
124
125 return array_merge($defaults, is_array($caps) ? $caps : []);
126 }
127
128 /**
129 * Capability map for Focus Pages.
130 *
131 * Focus Pages is Pro: it is bulk (many pages in one run), historical, and
132 * depends on Pro-only rank data (thinkrank-pro#164). Free has no entry
133 * point in v1 — the per-post SEO score panel already answers the single-page
134 * on-page question.
135 *
136 * Schema:
137 * enabled bool May curate and diagnose focus pages.
138 * max_pages int Pages that may be curated (0 = none).
139 *
140 * @since 2.5.0
141 *
142 * @return array Capability map.
143 */
144 public static function focus_pages(): array {
145 $defaults = [
146 'enabled' => false,
147 'max_pages' => 0,
148 ];
149
150 /**
151 * Filter the Focus Pages capability map.
152 *
153 * ThinkRank Pro enables the feature and declares its own page cap,
154 * which bounds the external API cost of a refresh.
155 *
156 * @since 2.5.0
157 *
158 * @param array $defaults Capability map (see schema above).
159 */
160 $caps = apply_filters('thinkrank_focus_pages_capabilities', $defaults);
161
162 return array_merge($defaults, is_array($caps) ? $caps : []);
163 }
164
165 /**
166 * Capability map for sitewide duplicate snippet detection.
167 *
168 * The check itself is Free: finding out that two of your pages carry one
169 * title is a read, it runs when the user asks for it, and it is exactly the
170 * kind of thing that should work on a first install (#564). What Pro adds
171 * is the unattended half — a recheck that runs on a schedule and tells you
172 * when a new duplicate appears, rather than when you next open the screen.
173 *
174 * Nothing in the free plugin schedules anything, so `scheduled` only ever
175 * reports what Pro has arranged; the report reads it to say whether it is
176 * being watched or only answered on demand.
177 *
178 * Schema:
179 * scheduled bool Duplicates are rechecked without the user asking.
180 *
181 * @since 2.10.0
182 *
183 * @return array Capability map.
184 */
185 public static function duplicate_snippets(): array {
186 $defaults = [
187 'scheduled' => false,
188 ];
189
190 /**
191 * Filter the duplicate snippets capability map.
192 *
193 * @since 2.10.0
194 *
195 * @param array $defaults Capability map (see schema above).
196 */
197 $caps = apply_filters('thinkrank_duplicate_snippets_capabilities', $defaults);
198
199 return array_merge($defaults, is_array($caps) ? $caps : []);
200 }
201
202 /**
203 * Capability map for the thin content report.
204 *
205 * Finding out which of your pages are thin is a read, it runs when the user
206 * asks for it, and it is exactly what should work on a first install, so
207 * the report is Free (#565). What Pro adds is the unattended half: an alert
208 * when content that was fine becomes thin, or when something thin is
209 * published, which is the decay framing Content Refresh Radar already uses.
210 *
211 * Nothing in the free plugin schedules anything, so `scheduled_alerts` only
212 * ever reports what Pro has arranged; the report reads it to say whether it
213 * is being watched or only answered on demand.
214 *
215 * Schema:
216 * scheduled_alerts bool Newly-thin content is reported without being asked.
217 *
218 * @since 2.10.0
219 *
220 * @return array Capability map.
221 */
222 public static function thin_content(): array {
223 $defaults = [
224 'scheduled_alerts' => false,
225 ];
226
227 /**
228 * Filter the thin content capability map.
229 *
230 * @since 2.10.0
231 *
232 * @param array $defaults Capability map (see schema above).
233 */
234 $caps = apply_filters('thinkrank_thin_content_capabilities', $defaults);
235
236 return array_merge($defaults, is_array($caps) ? $caps : []);
237 }
238
239 /**
240 * Check a single capability for a given feature.
241 *
242 * Adding a feature means adding a switch case to capabilities_for() that
243 * delegates to its own capability builder method.
244 *
245 * @param string $capability Capability key (e.g. 'usage_policy').
246 * @param string $feature Feature scope (e.g. 'llms_txt').
247 */
248 public static function can(string $capability, string $feature): bool {
249 $caps = self::capabilities_for($feature);
250 return ! empty($caps[$capability]);
251 }
252
253 /**
254 * Get the full capability map for a feature.
255 *
256 * @param string $feature Feature scope.
257 * @return array
258 */
259 public static function capabilities_for(string $feature): array {
260 switch ($feature) {
261 case 'llms_txt':
262 return self::llms_txt();
263 case 'seo_analyzer':
264 return self::seo_analyzer();
265 case 'focus_pages':
266 return self::focus_pages();
267 case 'duplicate_snippets':
268 return self::duplicate_snippets();
269 case 'thin_content':
270 return self::thin_content();
271 default:
272 return [];
273 }
274 }
275 }
276