From d2feb9319c611a1d4e0b374f816c569d74670a1b Mon Sep 17 00:00:00 2001 From: colorlink Date: Fri, 16 Oct 2026 04:26:26 +0000 Subject: [PATCH] Add tool-catalog patch: show guarded tools from absent plugins as locked groups with install note (per-group, collapsed) Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01Q8t9GEyyLZbUQu26na1JQg --- scripts/patch-tool-catalog.php | 185 +++++++++++++++++++++++++++++++++ 1 file changed, 185 insertions(+) create mode 100644 scripts/patch-tool-catalog.php diff --git a/scripts/patch-tool-catalog.php b/scripts/patch-tool-catalog.php new file mode 100644 index 0000000..e02dc2f --- /dev/null +++ b/scripts/patch-tool-catalog.php @@ -0,0 +1,185 @@ +getAllToolsRaw() as $t) { if (!empty($t['name'])) $live[$t['name']] = true; } + $labels = $this->ampPluginLabels(); + $groups = []; + foreach ($files as $f) { + $code = @file_get_contents($f); + if ($code === false || $code === '') continue; + if (!preg_match('/if\s*\(\s*!\s*(?:defined|class_exists)\s*\(\s*[\'"]\\\\?([A-Za-z0-9_\\\\]+)[\'"]\s*\)[^;\n]*\breturn\b/', $code, $gm)) continue; + $guard = ltrim($gm[1], '\\'); + if (!preg_match_all('/\$def\(\s*\'([a-z0-9_]+)\'\s*,\s*\'((?:\\\\.|[^\'\\\\])*)\'/', $code, $mm, PREG_SET_ORDER)) continue; + foreach ($mm as $m) { + $name = $m[1]; + if (isset($live[$name])) continue; // plugin active → already a real tool + $desc = str_replace(["\\'", "\\\\"], ["'", "\\"], $m[2]); + $info = $labels[$guard] ?? [$this->ampHumanizeGuard($guard), '']; + $gid = 'unavail_' . strtolower(preg_replace('/[^A-Za-z0-9]+/', '_', $guard)); + if (!isset($groups[$gid])) $groups[$gid] = ['label' => $info[0], 'plugin' => $info[0], 'tools' => []]; + $groups[$gid]['tools'][$name] = ['label' => $this->prettyLabel($name), 'description' => $desc]; + } + } + foreach ($groups as $gid => $g) { if (empty($g['tools'])) { unset($groups[$gid]); continue; } ksort($groups[$gid]['tools']); } + uasort($groups, fn($a, $b) => strcmp($a['label'], $b['label'])); + return $groups; + } + + private function ampPluginLabels(): array { + return [ + 'WPB_VC_VERSION' => ['WPBakery Page Builder', 'js_composer'], + 'ELEMENTOR_VERSION' => ['Elementor', 'elementor'], + 'WooCommerce' => ['WooCommerce', 'woocommerce'], + 'WOOCOMMERCE_VERSION' => ['WooCommerce', 'woocommerce'], + 'ICL_SITEPRESS_VERSION' => ['WPML', 'wpml'], + 'WPSEO_VERSION' => ['Yoast SEO', 'wordpress-seo'], + 'WORDFENCE_VERSION' => ['Wordfence Security', 'wordfence'], + 'LSCWP_V' => ['LiteSpeed Cache', 'litespeed-cache'], + 'LSCWP_CUR_V' => ['LiteSpeed Cache', 'litespeed-cache'], + 'WP_ROCKET_VERSION' => ['WP Rocket', 'wp-rocket'], + 'RANK_MATH_VERSION' => ['Rank Math SEO', 'seo-by-rank-math'], + 'AIOSEO_VERSION' => ['All in One SEO', 'all-in-one-seo-pack'], + 'SEOPRESS_VERSION' => ['SEOPress', 'wp-seopress'], + 'GFCommon' => ['Gravity Forms', 'gravityforms'], + 'FLUENTFORM_VERSION' => ['Fluent Forms', 'fluentform'], + 'ACF' => ['Advanced Custom Fields', 'advanced-custom-fields'], + 'TRP_PLUGIN_VERSION' => ['TranslatePress', 'translatepress-multilingual'], + 'POLYLANG_VERSION' => ['Polylang', 'polylang'], + 'ET_CORE_VERSION' => ['Divi', 'divi'], + ]; + } + + private function ampHumanizeGuard(string $g): string { + $g = preg_replace('/_(VERSION|VER|PLUGIN|CORE)$/i', '', $g); + $g = trim(str_replace(['_', '\\'], ' ', $g)); + return $g !== '' ? ucwords(strtolower($g)) : 'Add-on'; + } + + +PHP; + + $anchor = " private function prettyLabel(string \$n): string {"; + $n = substr_count($src, $anchor); + if ($n !== 1) { fwrite(STDERR, "prettyLabel anchor count=$n; aborting\n"); exit(2); } + $src = str_replace($anchor, $methods . $anchor, $src); + + $renderAnchor = " \n "; + $n = substr_count($src, $renderAnchor); + if ($n !== 1) { fwrite(STDERR, "render anchor count=$n; aborting\n"); exit(3); } + + $renderBlock = <<<'HTML' + + getUnavailableGrouped(); if (!empty($amp_unavail)): ?> +
+

Available with other plugins

+

These tools stay off because the plugin that drives them isn’t active on this site. Install & activate it and they switch on automatically — listed here so you can see the full catalog.

+
+ $amp_cat): $amp_total = count($amp_cat['tools']); ?> +
+

+ + locked + Not installed +

+

Requires — install & activate it to enable these tools.

+
+ $amp_tool): ?> +
+ + + + + + +
+ +
+
+ + + +HTML; + + $src = str_replace($renderAnchor, $renderBlock, $src); + + if (file_put_contents($admin, $src) === false) { fwrite(STDERR, "write failed $admin\n"); exit(4); } + $changed[] = 'AdminMenu.php (methods + render block)'; +} else { + $changed[] = 'AdminMenu.php already patched (skipped)'; +} + +/* ── 2. admin.css ─────────────────────────────────────────────────────────── */ +$cssSrc = @file_get_contents($css); +if ($cssSrc === false) { + fwrite(STDERR, "warning: cannot read $css\n"); +} elseif (strpos($cssSrc, 'amp-tool-catalog') === false) { + $cssAdd = <<<'CSS' + + +/* amp-tool-catalog: locked / not-installed families */ +.asktam-mcp-unavail-intro{margin:30px 0 8px;padding-top:18px;border-top:1px solid #e2e4e7} +.asktam-mcp-unavail-title{font-size:15px;margin:0 0 4px} +.asktam-mcp-category--locked{opacity:.95} +.asktam-mcp-category--locked .asktam-mcp-category-header{color:#50575e} +.asktam-mcp-locked-flag{display:inline-block;margin-left:8px;padding:1px 8px;border-radius:10px;background:#f0f0f1;color:#646970;font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:.02em;vertical-align:middle} +.asktam-mcp-count-locked{background:#f6f7f7;color:#646970} +.asktam-mcp-install-note{margin:2px 0 12px;padding:9px 12px;background:#fcf9e8;border:1px solid #f0e6a6;border-radius:6px;color:#674f00;font-size:12.5px} +.asktam-mcp-install-note strong{color:#674f00} +.asktam-mcp-category.is-collapsed .asktam-mcp-install-note{display:none} +.asktam-mcp-locked-card{display:flex;align-items:flex-start;gap:10px;padding:12px 14px;border:1px dashed #d5d8dc;border-radius:8px;background:#fafbfc;cursor:not-allowed} +.asktam-mcp-locked-card .asktam-mcp-lock{font-size:14px;line-height:1.5;filter:grayscale(1);opacity:.7} +.asktam-mcp-locked-card .asktam-mcp-tool-info{display:flex;flex-direction:column;gap:3px;min-width:0} +.asktam-mcp-locked-card .asktam-mcp-tool-name{font-weight:600;color:#50575e} +.asktam-mcp-locked-card .asktam-mcp-tool-desc{color:#787c82;font-size:12px} +.asktam-mcp-locked-card .asktam-mcp-tool-slug{color:#8c8f94;font-size:11px} +@media(prefers-color-scheme:dark){ +.asktam-mcp-unavail-intro{border-top-color:#3c434a} +.asktam-mcp-install-note{background:#2b2718;border-color:#5a4e1f;color:#e8d98a} +.asktam-mcp-install-note strong{color:#f3e7a0} +.asktam-mcp-locked-card{background:#1f2327;border-color:#3c434a} +.asktam-mcp-locked-card .asktam-mcp-tool-name{color:#c3c4c7} +.asktam-mcp-locked-flag,.asktam-mcp-count-locked{background:#2c3338;color:#a7aaad} +} +CSS; + file_put_contents($css, $cssAdd, FILE_APPEND); + $changed[] = 'admin.css (locked styles appended)'; +} else { + $changed[] = 'admin.css already patched (skipped)'; +} + +echo "patch-tool-catalog: " . implode('; ', $changed) . "\n";