PluginProbe
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot / 4.9.2
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot v4.9.2
4.9.2 4.9.1 4.9.0 4.8.2 4.8.1 4.8.0 4.7.0 4.6.2 4.6.1 4.6.0 4.5.6 4.5.5 4.5.4 4.5.3 4.5.2 4.5.1 4.5.0 4.4.1 4.4.0 3.3.4 3.4.0 3.4.1 3.4.2 3.5.0 3.5.1 All 200 releases
← All changes | includes/Editors/Elementor/TemplateSource.php +286 -90 3.4.24.9.2 View file →
@@ -2,9 +2,9 @@
2 2
3 3 namespace WPDeveloper\BetterDocs\Editors\Elementor;
4 4
5 5 if ( ! defined( 'ABSPATH' ) ) {
6 - exit; // Exit if accessed directly
6 + exit; // Exit if accessed directly
7 7 }
8 8
9 9 use Elementor\TemplateLibrary\Source_Base;
10 10
@@ -17,113 +17,309 @@
17 17 * @subpackage BetterDocs/elementor
18 18 * @author WPDeveloper <support@wpdeveloper.com>
19 19 */
20 20 class TemplateSource extends Source_Base {
21 - protected $template_prefix = 'betterdocs_';
22 - protected $cloud_url = 'https://betterdocs.co/wp-json/bd_cloud/v1/';
21 + protected $template_prefix = 'betterdocs_';
22 + protected $cloud_url = 'https://betterdocs.co/wp-json/bd_cloud/v1/';
23 23
24 - public function get_prefix() {
25 - return $this->template_prefix;
26 - }
24 + /**
25 + * Local template IDs (templates bundled with the plugin)
26 + */
27 + const LOCAL_TAG_ARCHIVE_ID = 'betterdocs_local_tag_archive_1';
27 28
28 - public function get_id() {
29 - return 'betterdocs-templates';
30 - }
29 + public function get_prefix() {
30 + return $this->template_prefix;
31 + }
31 32
32 - public function get_title() {
33 - return __( 'BetterDocs Templates', 'betterdocs' );
34 - }
33 + public function get_id() {
34 + return 'betterdocs-templates';
35 + }
35 36
36 - public function register_data() {}
37 + public function get_title() {
38 + return __( 'BetterDocs Templates', 'betterdocs' );
39 + }
37 40
38 - public function get_items( $args = [] ) {
39 - $url = $this->cloud_url . 'templates';
40 - $response = wp_remote_get( $url, ['timeout' => 60] );
41 - $body = wp_remote_retrieve_body( $response );
42 - $body = json_decode( $body, true );
43 - $templates_data = ! empty( $body['data'] ) ? $body['data'] : [];
44 - $templates = [];
41 + public function register_data() {}
45 42
46 - if ( ! empty( $templates_data ) ) {
47 - foreach ( $templates_data as $template_data ) {
48 - $templates[] = $this->prepare_template( $template_data );
49 - }
50 - }
43 + public function get_items( $args = [] ) {
44 + $_cache_key = 'betterdocs_remote_templates_v1';
45 + $templates = get_transient( $_cache_key );
51 46
52 - if ( ! empty( $args ) ) {
53 - $templates = wp_list_filter( $templates, $args );
54 - }
47 + if ( false === $templates ) {
48 + $templates = [];
55 49
56 - return $templates;
57 - }
50 + // Fetch remote templates
51 + $url = $this->cloud_url . 'templates';
52 + $response = wp_remote_get( $url, [ 'timeout' => 60 ] );
53 + $body = wp_remote_retrieve_body( $response );
54 + $body = json_decode( $body, true );
55 + $templates_data = ! empty( $body['data'] ) ? $body['data'] : [];
58 56
59 - public function prepare_template( $template_data ) {
60 - return [
61 - 'accessLevel' => 0,
62 - 'template_id' => $template_data['template_id'],
63 - 'source' => 'remote',
64 - 'type' => $template_data['type'],
65 - 'subtype' => $template_data['subtype'],
66 - 'title' => $template_data['title'],
67 - 'thumbnail' => $template_data['thumbnail'],
68 - 'date' => $template_data['date'],
69 - 'author' => $template_data['author'],
70 - 'tags' => $template_data['tags'],
71 - 'isPro' => ( 1 == $template_data['isPro'] ),
72 - 'popularityIndex' => (int) $template_data['popularityIndex'],
73 - 'trendIndex' => (int) $template_data['trendIndex'],
74 - 'hasPageSettings' => ( 1 == $template_data['hasPageSettings'] ),
75 - 'url' => $template_data['url'],
76 - 'favorite' => ( 1 == $template_data['favorite'] )
77 - ];
78 - }
57 + if ( ! empty( $templates_data ) ) {
58 + foreach ( $templates_data as $template_data ) {
59 + $templates[] = $this->prepare_template( $template_data );
60 + }
61 + }
79 62
80 - /**
81 - * Get remote template.
82 - *
83 - * Retrieve a single remote template from betterdocs.co
84 - *
85 - * @since 1.0.0
86 - * @access public
87 - *
88 - * @param int $template_id The template ID.
89 - *
90 - * @return array Remote template.
91 - */
92 - public function get_item( $template_id ) {
93 - $templates = $this->get_items();
63 + set_transient( $_cache_key, $templates, DAY_IN_SECONDS );
64 + }
94 65
95 - return $templates[$template_id];
96 - }
66 + // Note: local bundled templates are NOT included here.
67 + // They are injected exclusively via Elementor.php::get_templates() → http_response filter
68 + // to avoid duplicates (Elementor calls get_items() on registered sources separately).
97 69
98 - public function save_item( $template_data ) {
99 - return false;
100 - }
70 + if ( ! empty( $args ) ) {
71 + $templates = wp_list_filter( $templates, $args );
72 + }
101 73
102 - public function update_item( $new_data ) {
103 - return false;
104 - }
74 + return $templates;
75 + }
105 76
106 - public function delete_template( $template_id ) {
107 - return false;
108 - }
77 + /**
78 + * Returns locally bundled premade templates (no remote fetch required).
79 + *
80 + * @return array
81 + */
82 + public function get_local_templates() {
83 + return [
84 + [
85 + 'accessLevel' => 0,
86 + 'template_id' => self::LOCAL_TAG_ARCHIVE_ID,
87 + 'source' => 'remote',
88 + 'type' => 'block',
89 + 'subtype' => 'Docs Archive',
90 + 'title' => __( 'BetterDocs Tag Archive', 'betterdocs' ),
91 + 'thumbnail' => plugins_url( '/assets/static/admin/images/templates/tag-archive-thumb.png', BETTERDOCS_PLUGIN_FILE ),
92 + 'date' => '2024-01-01',
93 + 'author' => 'WPDeveloper',
94 + 'tags' => [ 'Docs Archive' ],
95 + 'isPro' => false,
96 + 'popularityIndex' => 0,
97 + 'trendIndex' => 0,
98 + 'hasPageSettings' => false,
99 + 'url' => plugins_url( '/assets/static/admin/images/templates/tag-archive-thumb.png', BETTERDOCS_PLUGIN_FILE ),
100 + 'favorite' => false,
101 + ],
102 + ];
103 + }
109 104
110 - public function export_template( $template_id ) {
111 - return false;
112 - }
105 + public function prepare_template( $template_data ) {
106 + return [
107 + 'accessLevel' => 0,
108 + 'template_id' => $template_data['template_id'],
109 + 'source' => 'remote',
110 + 'type' => $template_data['type'],
111 + 'subtype' => $template_data['subtype'],
112 + 'title' => $template_data['title'],
113 + 'thumbnail' => $template_data['thumbnail'],
114 + 'date' => $template_data['date'],
115 + 'author' => $template_data['author'],
116 + 'tags' => $template_data['tags'],
117 + 'isPro' => ( 1 == $template_data['isPro'] ),
118 + 'popularityIndex' => (int) $template_data['popularityIndex'],
119 + 'trendIndex' => (int) $template_data['trendIndex'],
120 + 'hasPageSettings' => ( 1 == $template_data['hasPageSettings'] ),
121 + 'url' => $template_data['url'],
122 + 'favorite' => ( 1 == $template_data['favorite'] )
123 + ];
124 + }
113 125
114 - public function get_data( array $args, $context = 'display' ) {
115 - $file_url = $this->cloud_url . 'template/' . $args['template_id'];
116 - $request = wp_remote_get( $file_url );
117 - $response = wp_remote_retrieve_body( $request );
118 - $body = json_decode( $response, true );
119 - $data = ! empty( $body['data'] ) ? $body['data'] : false;
126 + /**
127 + * Get remote template.
128 + *
129 + * Retrieve a single remote template from betterdocs.co
130 + *
131 + * @since 1.0.0
132 + * @access public
133 + *
134 + * @param int $template_id The template ID.
135 + *
136 + * @return array Remote template.
137 + */
138 + public function get_item( $template_id ) {
139 + $templates = $this->get_items();
120 140
121 - $result = [];
141 + return $templates[ $template_id ];
142 + }
122 143
123 - $result['content'] = $this->replace_elements_ids( $data );
124 - $result['content'] = $this->process_export_import_content( $result['content'], 'on_import' );
125 - $result['page_settings'] = [];
144 + public function save_item( $template_data ) {
145 + return false;
146 + }
126 147
127 - return $result;
128 - }
148 + public function update_item( $new_data ) {
149 + return false;
150 + }
151 +
152 + public function delete_template( $template_id ) {
153 + return false;
154 + }
155 +
156 + public function export_template( $template_id ) {
157 + return false;
158 + }
159 +
160 + public function get_data( array $args, $context = 'display' ) {
161 + // Serve local bundled templates without a remote HTTP request
162 + if ( isset( $args['template_id'] ) && $args['template_id'] === self::LOCAL_TAG_ARCHIVE_ID ) {
163 + return $this->get_local_tag_archive_data();
164 + }
165 +
166 + $file_url = $this->cloud_url . 'template/' . $args['template_id'];
167 + $request = wp_remote_get( $file_url );
168 + $response = wp_remote_retrieve_body( $request );
169 + $body = json_decode( $response, true );
170 + $data = ! empty( $body['data'] ) ? $body['data'] : false;
171 +
172 + $result = [];
173 +
174 + $result['content'] = $this->replace_elements_ids( $data );
175 + $result['content'] = $this->process_export_import_content( $result['content'], 'on_import' );
176 + $result['page_settings'] = [];
177 +
178 + return $result;
179 + }
180 +
181 + /**
182 + * Returns the Elementor template content for the Tag Archive premade template.
183 + * Layout (mirrors the screenshot): Search bar (full-width) + Sidebar / Content two-column area.
184 + *
185 + * @return array
186 + */
187 + protected function get_local_tag_archive_data() {
188 + $content = [
189 + // ── Row 1: Search bar (full-width container) ──────────────────────
190 + [
191 + 'id' => 'bdta0001',
192 + 'elType' => 'container',
193 + 'settings' => [
194 + 'flex_direction' => 'row',
195 + 'content_width' => 'full',
196 + 'padding' => [
197 + 'unit' => 'px',
198 + 'top' => '20',
199 + 'right' => '20',
200 + 'bottom' => '20',
201 + 'left' => '20',
202 + 'isLinked' => false,
203 + ],
204 + ],
205 + 'elements' => [
206 + [
207 + 'id' => 'bdta0003',
208 + 'elType' => 'widget',
209 + 'widgetType' => 'betterdocs-search-form',
210 + 'settings' => [],
211 + 'elements' => [],
212 + ],
213 + ],
214 + ],
215 +
216 + // ── Row 2: Sidebar (33 %) + Content (67 %) ───────────────────────
217 + [
218 + 'id' => 'bdta0010',
219 + 'elType' => 'container',
220 + 'settings' => [
221 + 'flex_direction' => 'row',
222 + 'content_width' => 'full',
223 + 'gap' => [
224 + 'unit' => 'px',
225 + 'size' => 0,
226 + ],
227 + 'padding' => [
228 + 'unit' => 'px',
229 + 'top' => '30',
230 + 'right' => '20',
231 + 'bottom' => '40',
232 + 'left' => '20',
233 + 'isLinked' => false,
234 + ],
235 + ],
236 + 'elements' => [
237 +
238 + // Left container – BetterDocs Sidebar
239 + [
240 + 'id' => 'bdta0011',
241 + 'elType' => 'container',
242 + 'settings' => [
243 + 'flex_direction' => 'column',
244 + 'content_width' => 'full',
245 + 'width' => [
246 + 'unit' => '%',
247 + 'size' => 33,
248 + ],
249 + ],
250 + 'elements' => [
251 + [
252 + 'id' => 'bdta0012',
253 + 'elType' => 'widget',
254 + 'widgetType' => 'betterdocs-sidebar',
255 + 'settings' => [],
256 + 'elements' => [],
257 + ],
258 + ],
259 + ],
260 +
261 + // Right container – Breadcrumbs + Tag title + Doc list
262 + [
263 + 'id' => 'bdta0020',
264 + 'elType' => 'container',
265 + 'settings' => [
266 + 'flex_direction' => 'column',
267 + 'content_width' => 'full',
268 + 'width' => [
269 + 'unit' => '%',
270 + 'size' => 67,
271 + ],
272 + 'padding' => [
273 + 'unit' => 'px',
274 + 'top' => '0',
275 + 'right' => '0',
276 + 'bottom' => '0',
277 + 'left' => '30',
278 + 'isLinked' => false,
279 + ],
280 + ],
281 + 'elements' => [
282 + // Breadcrumbs
283 + [
284 + 'id' => 'bdta0021',
285 + 'elType' => 'widget',
286 + 'widgetType' => 'betterdocs-breadcrumb',
287 + 'settings' => [],
288 + 'elements' => [],
289 + ],
290 +
291 + // Archive title – shows "Docs Tag: <tag-name>" dynamically
292 + [
293 + 'id' => 'bdta0022',
294 + 'elType' => 'widget',
295 + 'widgetType' => 'theme-archive-title',
296 + 'settings' => [
297 + 'title_size' => 'h2',
298 + ],
299 + 'elements' => [],
300 + ],
301 +
302 + // Docs list for the current tag
303 + [
304 + 'id' => 'bdta0023',
305 + 'elType' => 'widget',
306 + 'widgetType' => 'betterdocs-category-archive-list',
307 + 'settings' => [
308 + 'section_betterdocs_archive_list_layout' => 'layout-1',
309 + ],
310 + 'elements' => [],
311 + ],
312 + ],
313 + ],
314 + ],
315 + ],
316 + ];
317 +
318 + $result = [];
319 + $result['content'] = $this->replace_elements_ids( $content );
320 + $result['content'] = $this->process_export_import_content( $result['content'], 'on_import' );
321 + $result['page_settings'] = [];
322 +
323 + return $result;
324 + }
129 325 }