PluginProbe
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO / trunk
ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO vtrunk
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 1.0.2 1.1.0 1.10.0 1.11.0 All 47 releases
thinkrank / includes / editor / class-beaver-modules-manager.php

class-beaver-modules-manager.php in ThinkRank AI SEO – AI SEO Plugin for WordPress: Schema, XML Sitemaps, Meta Tags, Search Console & Local SEO trunk, at includes/editor/class-beaver-modules-manager.php

160 lines 5.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Beaver Builder Modules Integration Manager
5 *
6 * Registers ThinkRank's Beaver Builder modules (FAQ, HowTo, Table of Contents)
7 * so a Beaver-built page can emit FAQPage, HowTo and SiteNavigationElement
8 * schema the same way a Gutenberg, Elementor or Bricks page already can (#662).
9 *
10 * Neither the Elementor widgets nor the Bricks elements port. Each builder has
11 * its own API: Elementor has `Widget_Base` with `Controls_Manager`/`Repeater`,
12 * Bricks has `Bricks\Element` with a `set_controls()` array, and Beaver Builder
13 * has `FLBuilderModule` plus a nested tabs/sections/fields array handed to
14 * `FLBuilder::register_module()`. What IS shared is the rendered markup and the
15 * stylesheets, so all four builders paint the same component from the same CSS.
16 *
17 * Two Beaver-specific shapes are worth knowing before reading the modules:
18 *
19 * - **Repeaters are a separate registration.** A repeating field is
20 * `[ 'type' => 'form', 'form' => '<id>', 'multiple' => true ]`, and `<id>`
21 * is a form registered independently through
22 * `FLBuilder::register_settings_form()`. Elementor and Bricks both declare
23 * their repeater's sub-fields inline instead.
24 * - **Rendering goes through a file, not a method.** Beaver Builder renders a
25 * module by `include`ing `<module dir>/includes/frontend.php` with `$module`
26 * and `$settings` in scope. Each of ours is a one-line delegate to a method
27 * on the module class, so the logic stays testable and stays next to the
28 * settings it reads.
29 *
30 * Registration runs on `init` at 11. Beaver Builder loads `FLBuilderModule` on
31 * `plugins_loaded`, so anything earlier risks extending a class that does not
32 * exist yet; 11 also matches the Bricks manager for the same reason.
33 *
34 * All hooks are Beaver-gated: without the plugin, none of this runs and no
35 * `FLBuilder*` class is referenced.
36 *
37 * @package ThinkRank
38 * @subpackage Editor
39 * @since 2.5.0
40 */
41
42 declare(strict_types=1);
43
44 namespace ThinkRank\Editor;
45
46 // Prevent direct access
47 if (!defined('ABSPATH')) {
48 exit;
49 }
50
51 /**
52 * Beaver Builder Modules Manager.
53 *
54 * @since 2.5.0
55 */
56 class Beaver_Modules_Manager {
57
58 /**
59 * Module slug => directory name, in panel order.
60 *
61 * The slug is set explicitly on each module rather than left to Beaver
62 * Builder's default, which derives it from the class file's basename — a
63 * bare `faq` would be a slug collision waiting to happen with any other
64 * plugin's FAQ module, and the slug is what Beaver Builder keys its module
65 * registry and its `fl-module-<slug>` class on.
66 *
67 * @var array<string,string>
68 */
69 private const MODULES = [
70 'thinkrank-faq' => 'faq',
71 'thinkrank-howto' => 'howto',
72 'thinkrank-toc' => 'toc',
73 ];
74
75 /**
76 * Module slug => the shared block stylesheet it renders against.
77 *
78 * The modules reuse the Gutenberg blocks' compiled CSS rather than shipping
79 * a second copy, so a page built either way looks the same.
80 *
81 * @var array<string,string>
82 */
83 private const STYLES = [
84 'thinkrank-faq' => 'faq-block',
85 'thinkrank-howto' => 'howto-block',
86 'thinkrank-toc' => 'toc-block',
87 ];
88
89 /**
90 * Wire up hooks. Safe without Beaver Builder — every one of them checks.
91 *
92 * @return void
93 */
94 public function init(): void {
95 add_action('init', [$this, 'register_modules'], 11);
96 add_action('wp_enqueue_scripts', [$this, 'register_styles']);
97 }
98
99 /**
100 * Load the module files, each of which registers itself.
101 *
102 * Loading the file is what registers the module: every Beaver Builder
103 * module file ends in a `FLBuilder::register_module()` call, which is the
104 * convention its own modules and every third-party one follow. Requiring
105 * them behind this gate is what keeps `FLBuilderModule` from being extended
106 * on a site without the plugin — a fatal error, not a warning.
107 *
108 * @return void
109 */
110 public function register_modules(): void {
111 if (!class_exists('\\FLBuilder') || !class_exists('\\FLBuilderModule')) {
112 return;
113 }
114
115 foreach (self::MODULES as $dir) {
116 $file = THINKRANK_PLUGIN_DIR . "includes/editor/beaver/{$dir}/{$dir}.php";
117 if (is_readable($file)) {
118 require_once $file;
119 }
120 }
121 }
122
123 /**
124 * Register (not enqueue) the shared block stylesheets.
125 *
126 * Each module enqueues its own handle as it renders, so a page with no
127 * ThinkRank module loads none of this CSS.
128 *
129 * Registration is skipped for a handle another integration already
130 * registered: the Elementor and Bricks managers register the same three on
131 * the same hook, and a site running two builders would otherwise register
132 * twice.
133 *
134 * @return void
135 */
136 public function register_styles(): void {
137 foreach (self::STYLES as $handle) {
138 $style_handle = "thinkrank-{$handle}";
139 if (wp_style_is($style_handle, 'registered')) {
140 continue;
141 }
142
143 $css = THINKRANK_PLUGIN_DIR . "assets/{$handle}.css";
144 if (!file_exists($css)) {
145 continue;
146 }
147
148 $asset_path = THINKRANK_PLUGIN_DIR . "assets/{$handle}.asset.php";
149 $asset = file_exists($asset_path) ? include $asset_path : [];
150
151 wp_register_style(
152 $style_handle,
153 THINKRANK_PLUGIN_URL . "assets/{$handle}.css",
154 [],
155 $asset['version'] ?? THINKRANK_VERSION
156 );
157 }
158 }
159 }
160